Длинный опрос замораживает браузер и блокирует другой запрос ajax

Я пытаюсь реализовать опрос в моем Spring-MVC Web App но он замораживает мой браузер и другой запрос после 4-5 продолжает запросы AJAX.Я понятия не имею, что здесь происходит, это мой соответствующий код.

метод контроллера: (серверная сторона): -

@Asynchronous
    @RequestMapping("/notify")
    public @ResponseBody
    Events notifyEvent(HttpServletRequest request) {
        Events events = null;
        try {
            events = (Events) request.getSession(false).getServletContext().getAttribute("events");
            System.out.println("Request Came from" + ((com.hcdc.coedp.safe.domain.User) request.getSession(false).getAttribute(Constants.KEY_LOGGED_IN_USER)).getLoginId());
            if (!events.getTypeOfEvents().isEmpty()) {
                System.out.println("Removing older entries");
                events.getTypeOfEvents().clear();
            }
            while (!events.isHappend()) {
                //Waiting for event to happen.
            }
            events = Events.getInstance();
            events.setHappend(false);
            request.getSession(false).getServletContext().setAttribute("events", events);

        }catch (Exception e) {
            e.printStackTrace();
        }
        return events;
    }

скрипт длинного опроса (на стороне клиента): -

$(document).ready(function() {
                    $.ajaxSetup({
                        async:true//set a global ajax requests as asynchronus
                    });
                     alert('Handler for .onload() called.');
                    waitForMsg();

                });
                function waitForMsg(){

                    xhr=  $.ajax({
                        type: "POST",
                        url: '<%=request.getContextPath()%>/notification/notify',

                        async: true, /* If set to non-async, browser shows page as "Loading.."*/
                        cache: false,
                        timeout:50000, /* Timeout in ms */
                        global:false,
                        success: function(data){ /* called when request to notifier completes */
                          /* Doing smthing with response **/
                            setTimeout(
                            waitForMsg, /* Request next message */
                            1000 /* ..after 1 seconds */
                        );
                        },
                        error: function(XMLHttpRequest, textStatus, errorThrown){
                            addmsg("error", textStatus + " (" + errorThrown + ")");
                            setTimeout(
                            waitForMsg, /* Try again after.. */
                            15000); /* milliseconds (15seconds) */
                        }
                    });
                };

обновление:

function updateFeed(event, data) {
                var f=eval(data);
                alert(f.typeOfEvents.length);
            }

            function catchAll(event, data, type) {
                console.log(data);
                alert("error");
                console.log(type);
            }

            $.comet.connect('<%=request.getContextPath()%>/notification/notify');
            $(document).bind('feed.comet', updateFeed);
            $(document).bind('.comet', catchAll);

ни одно окно оповещения не появляется..:(

7 ответов


кажется, у вас есть пустой цикл while в коде браузера.. это очень процессора интенсивного курса способ, чтобы ждать события.

Если никаких событий не произойдет, клиент убьет запрос после желаемого тайм-аута 50 секунд. Но я не уверен, что поток сервера тоже убит, или если он" whiles " навсегда (если нет события). Следующий запрос запустит второй поток сервера, который также зависает в цикле while. Возможно, количество пустых циклов while является излишним для сервер, чтобы он перестал принимать какие-либо запросы. Поэтому после некоторых запросов (каждый из которых запускал бесконечный поток сервера) клиент всегда ждет нового запроса.. потому что он не может быть обработан сервером.

ps: при успехе вы прокомментировали, чтобы подождать 1 секунду, но установите тайм-аут 10000 (10 секунд)


Похоже, вы испытали блокировку файла сеанса

для PHP

использовать session_write_close() когда вам не нужно значение сеанса


Я встретил аналогичную проблему, мой браузер был как-то застрял с AJAX-запросами. Подсказка: вместо использования waitForMsg () напрямую, попробовать setTimeout ("waitForMsg ()", 10).


FYI, вот проект, который может вам помочь:https://github.com/SeanOC/jquery.comet

В общем, я бы искал API-интерфейсы JavaScript comet, которые могут поддерживать веб-сокеты, если они доступны на клиенте / сервере с изящным резервным вариантом для длительного опроса. API должен обрабатывать все кровавые детали, позволяя вам сосредоточиться на приложении.

вот ссылка на старую статью dojo по этой теме: http://dojotoolkit.org/features/1.6/dojo-websocket

удачи.


вы можете попытаться переписать поведение с помощью jQuery deferred:

function setShortTimeout() {
    setTimeout(waitForMsg, 1000);
}

function setLongTimeout() {
    setTimeout(waitForMsg, 15000);
}

$(document).ready(function() {
                $.ajaxSetup({
                    async:true//set a global ajax requests as asynchronus
                });
                alert('Handler for .onload() called.');
                $.when(waitForMsg())
                    .done(successHandler, setShortTimeout)
                    .fail(errorHandler, setLongTimeout);

            });

            function waitForMsg(){
                return $.ajax({
                    type: "POST",
                    url: '<%=request.getContextPath()%>/notification/notify',
                    async: true, /* If set to non-async, browser shows page as "Loading.."*/
                    cache: false,
                    timeout:50000, /* Timeout in ms */
                    global:false
                });
            };

errorHandler и successHandler будет ваш успех: и ошибка: обратные вызовы, которые я опустил для ясности, с их удаленной частью setTimeout (так как теперь она является частью отложенного.done() and .fail() обратные вызовы).

Дайте мне знать, если это работает.


Я разработчик PHP, но я встретил вашу проблему, и это может быть то же самое поведение. Поэтому я даю вам мои 2 цента и надеюсь, что это поможет тебе.

строка, которая заставляет меня подозревать проблему:

events = (Events) request.getSession(false).getServletContext().getAttribute("events");

в PHP сеансы хранятся в файлах, и если мы долго опрашиваем скрипт php, пока сеанс открыт, мы встречаем гонки проблема.

принцип довольно прост:

  1. когда запрос открывается сеанс, файл заблокирован до сеанса закрывающийся.
  2. если другие запросы поступают на сервер, они будут заблокированы до сеанс освобождается от предыдущего запроса.

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


Это может быть так:

        xhr=  $.ajax({ (...)

в функции waitForMsg.

попробовать

    var xhr = (...)

возможно, вы объявляете xhr в глобальном объекте, что делает невозможным ответ на два разных запроса.