Chrome не обрабатывает запрос jquery ajax

У меня есть следующий запрос в jquery. Он читает "публиковать" адрес пары подписки/публикации Nginx, созданной с использованием модуля долгого опроса Nginx.

function requestNextBroadcast() {
        // never stops - every reply triggers next. 
        // and silent errors restart via long timeout. 
        getxhr = $.ajax({
            url: "/activity",
            // dataType: 'json',
            data: "id="+channel,
            timeout: 46000, // must be longer than max heartbeat to only trigger after silent error. 
            error: function(jqXHR, textStatus, errorThrown) {
                alert("Background failed "+textStatus);  // should never happen 
                getxhr.abort(); 
                requestNextBroadcast();  // try again
            },
            success: function(reply, textStatus, jqXHR) {
                handleRequest(reply);   // this is the normal result. 
                requestNextBroadcast(); 
            }
        });
    }

Код является частью чата. На каждое отправленное сообщение отвечает нулевой запрос (с сообщением 200/OK), но данные публикуются. Это код для чтения адреса подписки, когда данные возвращаются.

Используя тайм-аут, все люди в чате посылают простое сообщение каждые 30-40 секунд, даже если они ничего не набирают, поэтому есть данные для чтения этого кода - как минимум 2 и, возможно, больше сообщений на 40 секунд.

Код в 100% устойчив в EI и Firefox. Но один из прочитанных примерно 5 ошибок в Chrome.

При сбое Chrome это происходит с таймаутом 46 секунд.

В журнале отображается один или один запрос активности сети в любой момент времени.

Я просканировал этот код в течение 3 дней, пытаясь различной идеи. И каждый раз, когда IE и Firefox работают нормально, и Chrome терпит неудачу.

Одно из предложений, которое я видел, - сделать звонок синхронным, но это явно невозможно, потому что он слишком долго блокирует пользовательский интерфейс.

Изменить - у меня есть частичное решение: Код теперь этот

function requestNextBroadcast() {
    // never stops - every reply triggers next. 
    // and silent errors restart via long timeout. 
    getxhr = jQuery.ajax({
        url: "/activity",
        // dataType: 'json',
        data: "id="+channel,
        timeout: <?php echo $delay; ?>,
        error: function(jqXHR, textStatus, errorThrown) {
            window.status="GET error "+textStatus;
            setTimeout(requestNextBroadcast,20);  // try again
        },
        success: function(reply, textStatus, jqXHR) {
            handleRequest(reply);   // this is the normal result. 
            setTimeout(requestNextBroadcast,20); 
        }
    });
}

Результат иногда ответ задерживается до тех пор, пока не произойдет $delay (15000), тогда очереди в очереди поступают слишком быстро, чтобы следовать. Я не смог заставить его отправлять сообщения (только проверенные с отключением netwrok optomisation) с этим новым соглашением.

Я очень сомневаюсь, что задержки связаны с сетевыми проблемами - все машины являются виртуальными машинами на моей одной реальной машине, и нет других пользователей локальной локальной сети.

Изменить 2 (Пятница 2:30 BST) - Изменен код для использования promises - и POST действий начал показывать те же симптомы, но сторона приема начала работать нормально! (????!!!???). Это процедура POST - она ​​обрабатывает последовательность запросов, чтобы гарантировать, что только один за раз выдался.

function issuePostNow() {
    // reset heartbeat to dropout to send setTyping(false) in 30 to 40 seconds. 
    clearTimeout(dropoutat);
    dropoutat = setTimeout(function() {sendTyping(false);},  
                           30000 + 10000*Math.random()); 
    // and do send 
    var url = "handlechat.php?";
    if (postQueue.length > 0) {
        postData = postQueue[0];
        var postxhr = jQuery.ajax({ 
            type: 'POST',
            url: url,
            data: postData,
            timeout: 5000
        })
        postxhr.done(function(txt){
            postQueue.shift();  // remove this task
            if ((txt != null) && (txt.length > 0)) {
                alert("Error: unexpected post reply of: "+txt)
            }
            issuePostNow();
        });
        postxhr.fail(function(){
            alert(window.status="POST error "+postxhr.statusText);
            issuePostNow();
        });
    }
}

Примерно за одно действие в 8 вызов handlechat.php будет отключен и появится предупреждение. После подтверждения оповещения все сообщения в очереди поступают.

И я также заметил, что вызов handlechat был остановлен, прежде чем он написал сообщение, которое другие увидели бы. Мне интересно, может ли быть какая-то странная обработка сессионных данных php. Я знаю, что он тщательно ставит в очередь вызовы, чтобы данные сеанса не были повреждены, поэтому я старался использовать разные браузеры или разные машины. Существует только 2 рабочих потока php, однако php НЕ используется при обработке/активности или в обслуживании статического содержимого.

Я также думал, что это может быть нехваткой рабочих nginx или php-процессоров, поэтому я поднял их. Сейчас труднее добиться того, чтобы все провалилось, но все же возможно. Я предполагаю, что вызов /activity теперь терпит неудачу один раз в 30 раз и вообще не отбрасывает сообщения.

И спасибо, ребята, за ваш вклад.


Резюме результатов.

1) Это ошибка в Chrome, которая некоторое время находилась в коде.
2) С удачей ошибка может быть сделана, чтобы появиться как POST, который не отправлен, и, когда он истечет, он оставляет Chrome в таком состоянии, что повторное POST будет успешным.
3) Переменная, используемая для хранения возврата из $.ajax(), может быть локальной или глобальной. Новый (promises) и старый формат вызовы оба запускают ошибку.
4) Я не нашел работу или способ избежать ошибки.

Ян

Ответ 1

У меня была очень похожая проблема с Chrome. Я делаю вызов Ajax, чтобы получать время с сервера каждую секунду. Очевидно, что вызов Ajax должен быть асинхронным, потому что он заморозит интерфейс по таймауту, если он не будет. Но как только один из вызовов Ajax является сбоем, каждый последующий тоже. Сначала я попробовал установить тайм-аут на 100 мс, и это хорошо работало в IE и FF, но не в Chrome. Мое лучшее решение - установить тип POST и решить проблему с хром для меня:

   setInterval(function(){ 
      $.ajax({
         url: 'getTime.php',
         type: 'POST',
         async: true,
         timeout: 100,
         success: function() { console.log("success"); },
         error: function() { console.log("error"); }
       });
   }, 1000);

Update: Я считаю, что основная проблема здесь крошечный способ кеширования. Похоже, что когда один запрос выходит из строя, этот отказ кэшируется, и поэтому последующие запросы никогда не выполняются, потому что Chrome будет получать кешированный сбой до начала последующих запросов. Это можно увидеть, если перейти к инструментам разработчика Chrome и перейти на вкладку "Сеть" и изучить каждый сделанный запрос. Перед сбоем запросы ajax на getTime.php производятся каждую секунду, но после 1 сбой последующие запросы никогда не запускаются. Поэтому для меня работало следующее решение:

   setInterval(function(){ 
      $.ajax({
         url: 'getTime.php',
         cache: false,
         async: true,
         timeout: 100,
         success: function() { console.log("success"); },
         error: function() { console.log("error"); }
       });
   }, 1000);

Здесь я могу отключить кеширование этого Ajax-запроса, но для этого параметр типа должен быть GET или HEAD, поэтому я удалил 'type: 'POST'' (GET по умолчанию).

Ответ 2

попробуйте переместить функцию опроса в веб-сайт, чтобы предотвратить замерзание в хроме. В противном случае вы можете попробовать использовать athe ajax.done() объекта jquery. что я всегда работаю для меня в хроме.

Ответ 3

Мне кажется, что в getxhr должен быть префикс "var". Разве вам не нужен отдельный отдельный запрос каждый раз, а не переписывание старого в середине успешной/неудачной обработки? Мог бы объяснить, почему поведение "улучшается" при добавлении setTimeout. Я также мог бы пропустить что-то;)

Ответ 4

Комментарии не будут форматировать код, поэтому повторная отправка в качестве второго ответа:

Я думаю, что Майкл Диббетс на что-то с $.ajax.done - шаблон отложенного кода переводит обработку на следующий оборот цикла событий, который, я думаю, является поведением, которое здесь необходимо. см. http://www.bitstorm.org/weblog/2012-1/Deferred_and_promise_in_jQuery.html или http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/

Я бы попробовал что-то вроде:

function requestNextBroadcast() { 
  // never stops - every reply triggers next.
  // and silent errors restart via long timeout.

  getxhr = jQuery.ajax({
    url: "/activity",
    // dataType: 'json',
    data: "id="+channel,
    timeout: <?php echo $delay; ?> 
  });

  getxhr.done(function(reply){
    handleRequest(reply);
  });

  getxhr.fail(function(e){
    window.status="GET error " + e;
  });

  getxhr.always(function(){
    requestNextBroadcast();
  });

Примечание. Мне сложно найти документацию по аргументам обратного вызова для Promise.done и Promise.fail: (

Ответ 5

Возможно, это можно обойти, изменив настройки push-модуля (их несколько). Не могли бы вы опубликовать их?

С головы:

  • установив его на интервальный опрос, будет его явно решить.
  • Настройки concurrency могут иметь некоторый эффект
  • хранилище сообщений может использоваться для предотвращения отсутствия данных

Я также использовал бы что-то вроде Charles, чтобы узнать, что именно происходит в сетевых/прикладных слоях