Long polling freezes browser and blocks another ajax request

I am trying to implement a lengthy poll in my Spring-MVC web application , but it freezes my browser and another request after 4-5 continues the AJAX requests. I have no idea what is going on here - this is my corresponding code.

Controller Method: (server side): -

@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; } 

Long polling script (client side): -

 $(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) */ } }); }; 

UPDATE:

 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); 

No warning popup .:(

+7
source share
7 answers

It seems you have an empty while loop in your browser code. This is a very powerful way to calculate the timeout for an event.

If no events occur, the client will kill the request after the desired timeout of 50 seconds. But I'm not sure if the server thread is killed either, or if it is "whiles" forever (if there is no event). The following request will start a second server thread, which also hangs in a while loop. Perhaps the number of empty loops is an excess for the server, so it stops accepting any requests. Therefore, after some requests (each of which caused an endless stream of the server), the client waits forever for a new request .. because it cannot be processed by the server.

ps: you commented on success in order to wait 1 second, but set the timeout to 10000 (10 seconds)

+5
source

Looks like you encountered a session file lock

For php

Use session_write_close() when you don't need a session value

+9
source

I met a similar problem, my browser was somehow stuck with AJAX requests. Hint: instead of using waitForMsg (), directly try setTimeout ("waitForMsg ()", 10).

+2
source

FYI, here is a project that can help you: https://github.com/SeanOC/jquery.comet

In general, I would look for a comet com compilation API that can support web sockets if they are available on the client / server with a graceful departure from a lengthy survey. The API should handle all the details of gory, allowing you to focus on the application.

Here's a link to an old dojo related article: http://dojotoolkit.org/features/1.6/dojo-websocket

Good luck.

+2
source

You can try to rewrite the behavior using 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 and successHandler will be your success: and error: the callbacks that I omitted for clarity, with the setTimeout part removed (since now it is part of the deferred .done () and .fail () callbacks).

Let me know if it works.

+2
source

I am a PHP developer, but I met your problem, and this may be the same behavior. So I give you my 2 cents and hope this helps you.

The line that makes me suspect that the problem is:

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

In PHP, sessions are stored in files, and if we conduct a survey for a long time on a php script while the session is open, we meet a race condition .

The principle is quite simple:

  • When a request opens a session, the file is locked until the session is closed.
  • If other requests appear on the server, they will be blocked until the session is freed from the previous request.

In the case of a lengthy survey, if the session is open and not closed immediately after receiving information (at least before waiting for events), all requests are simply blocked, you can’t go anywhere on the website if you use sessions on other pages. Even if you open a new tab because there is only one session for one browser, you are blocked.

+2
source

Perhaps it:

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

in the waitForMsg function.

Try

  var xhr = (...) 

Perhaps you are declaring xhr in a global object, which makes it impossible to answer two different requests.

+1
source

All Articles