Длинный опрос замораживает браузер и блокирует другой запрос 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, пока сеанс открыт, мы встречаем гонки проблема.
принцип довольно прост:
- когда запрос открывается сеанс, файл заблокирован до сеанса закрывающийся.
- если другие запросы поступают на сервер, они будут заблокированы до сеанс освобождается от предыдущего запроса.
в случае длительного опроса, если сеанс открыт и не закрыт сразу после получения информации (по крайней мере, перед ожиданием событий), все запросы просто заблокированы, вы не можете пойти куда-либо еще на веб-сайте, если вы используете сеансы на других страницах. Даже если вы откроете новую вкладку, потому что для одного браузера есть только один сеанс, вы заблокированы.
Это может быть так:
xhr= $.ajax({ (...)
в функции waitForMsg.
попробовать
var xhr = (...)
возможно, вы объявляете xhr в глобальном объекте, что делает невозможным ответ на два разных запроса.