Длинный опрос замораживает браузер и блокирует другой запрос 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 7

7 ответов:

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

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

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

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

Для PHP

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

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

К вашему сведению, вот проект, который может вам помочь: https://github.com/SeanOC/jquery.comet

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

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

Хорошо удача.

Вы можете попробовать переписать поведение с помощью отложенного jQuery:

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 удалены (так как теперь это часть отложенного.сделано () и .fail() обратные вызовы).

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

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

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

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

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

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

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

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

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

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

В функции waitForMsg.

Попробуйте

    var xhr = (...)

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