【问题标题】:AppEngine channel API: duplicate messages client sideAppEngine 通道 API:重复消息客户端
【发布时间】:2017-01-08 08:25:54
【问题描述】:

我正在尝试使用 Channel API 将更新从服务器推送到客户端。流程是用户按下一个按钮,该按钮触发一个生成大量日志的服务器端操作。我想“实时”向用户显示日志。

当我第一次加载页面时,我会收到所有消息,没问题。如果我在浏览器中没有刷新页面而再次触发该操作,则所有消息都会出现两次。这是与页面 onLoad 事件相关联的通道的设置部分。通过生成的控制台日志,我收集到 onMessage() 方法在页面未刷新时被多次调用。看起来我需要以某种方式“杀死”早期的套接字,但在官方文档中找不到方法。有人可以为我指出正确的方向以消除虚假消息吗?

// First fetch a token for the async communication channel and
// create the socket
$.post("/app/channels", {'op':'fetch', 'id' : nonce},
   function (data, status, xhr) {
       if (status == "success") {
       data = JSON.parse(data);
       token = data["token"];
       console.log("Cookie: " + get_mp_did() + "; token: " + token);
       var channel = new goog.appengine.Channel(token);
       var handler = {
           'onopen': onOpened,
           'onmessage': onMessage,
           'onerror': function() {
               $("#cmd_output").append('Channel error.<br/>');
           },
           'onclose': function() {
           $("#cmd_output").append('The end.<br/>');
           $.post("/app/channels", {'op':'clear'});
           }
       };
       var socket = channel.open(handler);
       socket.onopen = onOpened;
       socket.onmessage = onMessage;
       }
   });

onOpened = function() {
$("#cmd_output").empty();
};

onMessage = function(data) {
message = JSON.parse(data.data)['message'];
$("#cmd_output").append(message);
console.log('Got this sucker: ' + message);
}

【问题讨论】:

    标签: google-app-engine channel-api


    【解决方案1】:

    如果我正确理解了您的帖子和代码,则用户单击调用$.post() 函数的按钮。服务器代码负责在 GAE 中创建通道作为对/app/channels 请求的响应。我认为您的服务器实际上会为每个后续请求创建一个新的通道客户端 ID/令牌。由于页面没有重新加载,任何后续请求都会向该客户端添加一个新通道。并且所有这些通道仍将连接(因此,不会刷新页面)。

    我假设您的服务器代码具有与用户关联的所有频道,并且您使用所有频道将消息发送给用户?这种模式会导致这种行为。您可以通过在不刷新页面的情况下单击按钮 3 或 4 次来验证我的假设。日志输出将乘以 3 或 4 倍。

    我建议您将令牌存储在客户端和服务器上。然后对您的客户端 JS 进行修改。如果通道已创建,则存储令牌值并将其提供给/app/channels 的任何后续请求。修改服务器,使其不会在请求中提供令牌时创建新通道。如果令牌链接到现有的有效通道,请重新使用该通道并在响应中返回相同的令牌。您可能需要为断开连接或过期的频道添加更多详细信息,也许还需要一个 cron-job 来在一段时间后删除所有过期的频道。

    【讨论】:

    • 嗯,实际上 (a) $.post() 在 jquery onLoad() 之后在客户端完成一次。 (b) 具体来说,不是每次用户按下按钮时都创建一个新频道。 (c) 我将令牌和 id 存储在服务器端,如果令牌可用,则重新发送令牌 (d) 发送消息时,我只发送到一个令牌,因此令人困惑的是消息如何进入多个通道但是每次按下按钮而不重新加载消息确实成倍增加。换句话说,我看到了一些不应该出现的情况......嗯。也许这是一些愚蠢的错误......让我调查一下
    • 调试问题后发现与通道 API 无关。每次调用时,我只是将处理程序添加到记录器中,并且它们在没有重新加载页面的情况下堆积起来。但我接受 Ani 的答案作为正确答案,因为如果由于 Channels API 问题而看到此行为,它包含所有需要检查的内容
    猜你喜欢
    • 1970-01-01
    • 2020-09-28
    • 2018-05-27
    • 1970-01-01
    • 2018-08-06
    • 2022-01-15
    • 1970-01-01
    • 2019-04-08
    • 2012-11-02
    相关资源
    最近更新 更多