2016-08-31 8 views
0

Channel APIを使用して、サーバーからクライアントに更新をプッシュしようとしています。このフローは、ユーザがボタンを押して、多くのログを生成するサーバ側のアクションを引き起こします。私はユーザーにログを "リアルタイムで"表示したいと思います。AppEngineチャネルAPI:クライアント側メッセージの複製

最初にページを読み込むと、すべてのメッセージが表示されますが問題ありません。ブラウザでページを更新せずにもう一度操作を実行すると、すべてのメッセージが2回表示されます。ページ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); 
} 

答えて

1

投稿とコードを正しく理解している場合、ユーザーは$.post()機能を呼び出すボタンをクリックします。サーバーコードは、/app/channelsリクエストへの応答としてGAEにチャネルを作成する責任があります。私はあなたのサーバーが、実際には、後続のリクエストごとに新しいチャンネルのクライアントID /トークンを作成すると思います。ページがリロードされないので、後続のリクエストはこのクライアントに新しいチャンネルを追加します。これらすべてのチャンネルはまだ接続されているため(ページはリフレッシュされません)。

あなたのサーバーコードには、すべてのチャンネルがユーザーに関連付けられているものとし、すべてのチャンネルを利用しているユーザーにメッセージを送信するとしますか?このようなパターンは、このような動作を引き起こします。私の前提を確認するには、ページを更新せずにボタンを3回または4回クリックします。ログの出力には3または4の係数が乗算されます。

クライアントとサーバーにトークンを格納することをお勧めします。その後、クライアントJSを変更します。チャネルがすでに作成されている場合は、トークン値を格納し、その後の任意の要求に/app/channelsへ提供します。要求にトークンが提供されている場合は、新しいチャネルを作成しないようにサーバーを変更します。トークンが既存の有効なチャネルにリンクしている場合は、チャネルを再利用して応答内の同じトークンを返します。切断または期限切れのチャンネルの詳細を追加する必要があります。しばらくすると、期限切れのチャンネルをすべて削除するためのcronジョブも必要です。

+0

実際には、(a)$ .post()はjquery onLoad()の後にクライアント側で一度実行されます。 (b)特に、ユーザーがボタンを押すたびに新しいチャンネルが作成されることはありません。 (c)トークンとIDをサーバ側に保存し、トークンがあればそれを再送する(d)メッセージを送信するとき、私はただ1つのトークンにしか送信しないので、メッセージが複数のチャネルに流れる方法を困惑させる。 しかし、リロードせずにボタンが押された時、メッセージは掛け算されます。言い換えれば、私はそうであってはならない何かを見ている。おそらくそれはいくつかのばかげたバグです...私に調査させてください – Karra

+0

問題をデバッグした後、チャンネルAPIには何も関係ないことが判明しました。すべての呼び出しで、私はロガーにハンドラーを追加するだけで、ページを再ロードせずに積み重なっていました。しかし、この問題がChannels APIの問題のために見られた場合、チェックする必要があるすべてのものがあるため、Aniの答えを正しい答えとして受け入れています – Karra

関連する問題