API канала AppEngine: дублирование сообщений на стороне клиента

Я пытаюсь использовать 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);
}

person Karra    schedule 31.08.2016    source источник


Ответы (1)


Если я правильно понимаю ваш пост и код, пользователь нажимает кнопку, которая вызывает функцию $.post(). Код сервера отвечает за создание канала в GAE в ответ на /app/channels запрос. Я думаю, что ваш сервер фактически создает новый идентификатор / токен клиента канала с каждым последующим запросом. Поскольку страница не перезагружается, любой последующий запрос добавит новый канал для этого клиента. И все эти каналы по-прежнему будут подключены (следовательно, обновление страницы не будет).

Я предполагаю, что ваш серверный код имеет все каналы, связанные с пользователем, и вы отправляете сообщение пользователю, используя все каналы? Такой образец привел бы к такому поведению. Вы можете проверить мое предположение, нажав 3 или четыре раза на кнопку без обновления страницы. Выходные данные журнала будут умножены на коэффициент 3 или 4.

Я предлагаю вам хранить токен в клиенте и на сервере. Затем внесите изменения в свой клиентский JS. Если канал уже создан, сохраните значение токена и предоставьте его для любого последующего запроса к /app/channels. Измените сервер так, чтобы он не создавал новый канал, если токен предоставлен с запросом. Если токен ссылается на существующий допустимый канал, повторно используйте канал и верните тот же токен в ответ. Возможно, вам потребуется добавить дополнительные сведения для отключенных или просроченных каналов, возможно, также задание cron для удаления всех просроченных каналов через некоторое время.

person Ani    schedule 08.09.2016
comment
Хм, на самом деле (а) $ .post () выполняется один раз на стороне клиента после jquery onLoad (). (b) В частности, новый канал не создается каждый раз, когда пользователь нажимает кнопку. (c) Я сохраняю токен и идентификатор на стороне сервера и повторно отправляю токен, если он доступен (d) При отправке сообщений я отправляю только один токен, поэтому сбивает с толку, как сообщения отправляются на несколько каналов. кнопка нажата без перезагрузки сообщения умножаются. Другими словами, я вижу то, чего не должно быть ... Хм. Возможно, это какая-то глупая ошибка ... позвольте мне разобраться - person Karra; 11.09.2016
comment
После устранения проблемы выяснилось, что она не имеет отношения к API каналов. При каждом вызове я просто добавлял обработчики в регистратор, и они накапливались без перезагрузки страницы. Но я принимаю ответ Ани как правильный ответ, поскольку в нем есть все, что нужно проверить, было ли такое поведение замечено из-за проблемы с API каналов. - person Karra; 13.09.2016