Start ajax server script and poll for completeness - javascript

I have an AJAX Request that takes a long time to complete executing. So long that it usually times out and just continues running on server. So I was thinking that if there was some way to just start it and occasionally poll the same request for completeness, that would be ideal.
So my question is can you run a server script, let it run, and poll occasionally to see if its completed? I'm using a web method to run on server if that helps/matters.
I don't want to store the data on a database so I cant just poll for the database so can I poll the script itself.
My fallback is however to create a temp table so I can call from it to see progress. Or is there some better way?

Firstly if you do not want your Ajax Request to timeout, you can use the 'timeout' attribute.
XMLHttpRequest object used for Ajax calls has a 'timeout' attribute. Check out the documentation at http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute .If you are making the Ajax call using jquery, you can simply do something like
$.ajax({
url: 'your url',
timeout: 100000 //this sets the timeout as 100 sec
……//your other attributes for the call
});
If you are interested in tracking your request progress, that might be a little difficult unless you want to track the completeness(complete), error, success or a particular status code. jquery provides different(complete, error, success and status code) properties for this. If you write a native ajax call(without query), the onreadystatechange event can track the following.
0 - Unsent, 1- Opened, 2 - Response_Headers received, 3 - Loading(response is being received), 4 - Done. More at http://www.w3.org/TR/XMLHttpRequest/#event-handlers.
Tracking anything besides this would be for you to develop, maintain and monitor in your code I think.

Related

Dojo: all xhr / ajax calls seem to be synchronous and block other calls

I am working on a CRM we inherited. Long story short - there is a button that calls a php script which should run in background and we don't need to wait for response.
request(idata+'transferInTimeExec.php',{
sync: false,
preventCache:true,
method:'GET'
});
Now, the transferInTimeExec.php takes an hour to run, it's a very complex script that deals with weekly timesheets for a recruitment company, processes them, does a lot of DB operations etc.
Using Chrome. Every time I press the button to run it, it blocks all the xhr calls until it finishes. CRM is "ajax heavy" and while the script is running, the user can't do anything, if they navigate to another subpage, no xhr requests will resolve until that process we started has finished. Even when I open a new browser tab and try to do something, it won't do it. If I open the CRM in another browser (Firefox) while the script is running, I can use the CRM.
In Network tab - the first one is pending, and as you can see all the subsequential calls to a different Ajax call wait (all have sync:false)
I even replaced the whole logic with PHP function sleep(30) to make it just do nothing for 30 seconds before returning anything - same issue.
I tried XHR in plain javascript, inside onClick on the button HTML markup, rather than Dojo methods - same issue.
I've done a brutal Search/Replace on the whole project, replacing sync:true to sync:false - nothing changed.
I have run out of ideas, maybe anyone here can help to figure this out? Is there a global switch for sync/async? What else could it be if not ajax issue?
Your script transferInTimeExec.php is probably using session. When thats the case, other AJAX Call would not initiate and instead wait for this AJAX Call to Finish so as to not overwrite the session data. Setting AJAX call to asynchronous does not change the behavior.
If this script takes 1 hour to run it is a bad idea to call it as an AJAX from UI. You should setup a Cron, hourly or daily, and perform all the operations in the backend. Of course, you will need to make some adjustment to the script if it is using session.
EDIT
You could use session_write_close(); at the top of your script. This tells the PHP that this script would not write anything to the Session so other AJAX Calls are free to use the Session. However be careful to not write anything to Session after this as this will result in an error.

jQuery $.get() is blocking other requests

I'm developing a web application and use jQuery to make asynchronous HTTP requests to my API. I have a detail view where you can see a lot of information of a specific object stored in the database. Because there is a lot of information and data that is linked to other objects, I make different calls to my API to gather different information for my views.
In the 'detail view' I have some kind of widgets that show the requested information. For that, I make about 5-7 HTTP GET requests to my API. When using the debugger (both Safari and Firefox), I can see that some requests are blocking other requests and the page takes a lot of time until everything is loaded and shown to the user.
I make a request like this:
$.get("api/api.php?object=myobject&endpoint=someendpoint", function(data) {
// data is JSON formatted
$("#my-widget input").val(data["name"]);
});
And another one e.g. like this:
$.get("api/api.php?object=anotherobject&endpoint=anotherendpoint", function(data) {
// data is JSON formatted
$("#other-widget input").val(data["somekey"]);
});
If the first request takes a little longer to finish, it blocks the second request until the callback function of the first request finished. But why? I thought that those calls are asynchronous and non-blocking.
I want to build a fast web application for a company where the requests are only made inside the local network, so a request should only take about 10-50ms (or even less). But the page takes about 10 seconds to show up with all information.
Am I doing something wrong? Or is there a JavaScript framework that can be used for exactly this problem? Any help is appreciated!
EDIT: As you can see in the screenshot, the requests have to wait some seconds, and if the request is fired, it takes a few seconds until a response comes back.
If I call the URL directly in my browser or do a GET request using curl it is a lot faster.
EDIT2: Thanks #CBroe! The session file write lock was the problem. As long as the session file is locked, no other script can run until the previous script finished. I just called session_write_close() immediately after session_start() and it runs a lot faster now.
Attention: Use session_write_close() only if you don't need to write to the $_SESSION array. Reading is possible after that, but writing not. (See this topic for further details: https://stackoverflow.com/a/50368260/1427878)

Does jquery post ever timeout?

Official documentation at jQuery does not mention it.
Possible confusion: I know I can use ajax to gain control over timeout, but my question is different.
Scenario:
I am using post to grab data from a backend which I know will take a long (sometimes very very long) time to load.
Question:
Will my javascript request ever timeout or will it always wait until backend is loaded, even if it takes a few minutes?
Jquery uses the native XMLHttpRequest module to make requests.
The XMLHttpRequest.timeout property is an unsigned long representing the number of milliseconds a request can take before automatically being terminated. The default value is 0, which means there is no timeout.
Reading the source code of the jquery library, the ajax method does not set a timeout in and way, hence it is save to say that the request does not timeout.
But you can explicitly set a timeout in both jquery and the native module.
this does not mean that your request will not timeout, since the server usually does impose a bail timeout strategy, usually long responses timeout from the server side. you could consider chunking or streaming as a safe and convenient solution.
github jquery ajax source:
https://github.com/jquery/jquery/tree/2d4f53416e5f74fa98e0c1d66b6f3c285a12f0ce/src/ajax
The timeout of a request is, by default, controlled by the browser and the receiving server, whichever cancels the request first. I believe most browsers have a 60 second timeout by default. The server can be any arbitrary value.
Will my javascript request ever timeout or will it always wait until backend is loaded, even if it takes a few minutes?
The answer to this is therefore, yes, your request will timeout at an arbitrary point. If you want to control the amount of time you force your users to wait for a request then you can specifically set this time by using the timeout property of the $.ajax call. This overrides any timeout set in the browser or on the server.
15 seconds should be more than enough. If a request is taking longer than that I'd suggest you change the pattern you're using to generate the response.
HTTP Request timeout is a server side configuration not a client side configuration. Requests submitted via Jquery code is no different.
You might want to have a test against the return code from the last request and add exception handling to your code (like resubmit the request)
Always check the response code and a common strategy is to rety. https://www.lifewire.com/g00/troubleshooting-network-error-messages-4102727

How to avoid synchronous AJAX without spawning sessions

My page loads all necessary data from the server at startup via AJAX. This includes user's language settings, various classifiers, some business data etc.
The problem I am facing is that when the user first comes to the page, all these different AJAX calls are kicked off at the same time. This means that on the server side, most of them are assigned different JSESSIONID-s (I am using Spring on Tomcat 8 without any complex configuration). As a result, some of the data is initialized on the server side in one session, but the browser might end up using a different session in the end and does not have access to the data set up by earlier ajax calls.
I wanted to solve this by using a fast synchronous AJAX call in the very beginning so that after it returns and gets a JSESSIONID, all subsequent calls would be made in this original session.
$.ajax("api/language", {
type: "GET",
cache: false,
async: false,
success: function(data) {
//do stuff;
}
});
// more AJAX calls
It works, but I get warning messages that synchronized XMLHttpRequest on main thread is deprecated. Now - I understand the reasons why such a synchronized call is bad for UI in general, but what other options are there available for me if I want to force all AJAX calls to use the same server side session?
I can achieve the same result by using a callback and just placing all the rest of my page initialization code in there, executing it in the 'success' section of the first AJAX call, but that wouldn't that have exactly the same effect as synchronizing on main?
I'd initiate the session when loading the HTML document rather than when requesting something from the API.
Alternatively, trigger the subsequent API calls from the success callback of the first one.
"Hacky" solution
You really give your own solution at the end: wrap everything in an asynchronous AJAX call. It is similiar to the synchronous solution, but this way you can set up a loading animation, or something similar.
"Nice" solution
Another, possible nicer solution. When the user arrives, you can redirect to the starting page of your web application with the generated jsessionid. This can be done with a servlet. I am quite sure that Tomcat can be configured to do this without writing your own code.

jQuery: Using a single Ajax call, receive progressive statuses instead of one single response?

I'm just wondering..is it possible to receive multiple responses from a single ajax call?
I'm thinking purely for aesthetic purposes to update the status on the client side.
I have a single ajax method that's called on form submit
$.ajax({
url: 'ajax-process.php',
data: data,
dataType: 'json',
type: 'post',
success: function (j) {
}
});
I can only get one response from the server-side. Is it possible to retrieve intermittent statuses? Such as:
Default (first): Creating account
Next: Sending email confirmation
Next: Done
Thanks for your help! :)
From a single ajax call, I don't think it is possible.
What you could do is check frequently where the process is (it's what is used for the upload bars in gmail for example). You do a first ajax request to launch the process, and then a series of ajax request to ask the server how he is doing. When the server answers "I'm done", you're good to go, and until that you can make the server respond and say the current state.
There is something called comet which you can set up to "push" requests to client, however it is probably way more than what you are wanting to invest in, time-wise.
You can open up a steady stream from the server, so that it continues to output, however I'm not sure how client-side script can handle these as individual "messages". Think about it like a server that outputs some info to the browser, does more work, outputs some more to the browser, does more work, etc. This shows up more or less in real time to the browser as printed text. It is one long response, but it is still one response. I think ajax only handles a response once it finished being sent, but maybe someone else will know more than me on the topic.
But you couldn't have the server output several individual responses without reloading itself, at least not with PHP, because once you start outputting the response, the response has begun and you can't chop that up without finishing the response, which happens when the script is done executing.
Your best bet is with the steady stream, but again, I'm not sure how ajax handles getting responses in chunks.
Quick Update
Based on the notes for this plugin:
[http://plugins.jquery.com/project/ajax-http-stream]
things don't look promising. Specifically:
Apparently the trend is to disallow access to the xmlhttprequest.responseText before the request is complete (stupid imo). Sorry there's nothing I can do to fix this
Thus, not only can you not get what you want in one request, you probably can't get it multiple requests, unless you want to break up the actual server-side process into several parts, and only have it continue to the next step when an ajax function triggers it.
Another option would be to have your script write it's status at specific points to another file on the server, call it "status.xml" or "status.txt". Have your first ajax function initialize the process, and have a second ajax function that queries this status file and outputs that to the user.
It is possible, but it has more to do with your backend script. As Anthony mentioned there is a tech called comet. Another term I've heard is called "Long polling". The idea is that you delay the time in which your php(insert language of choice) script finished processing.
In php you can do something like this:
while($response !== 'I'm done'){
sleep(1);
}else{
return $some_value;
exit();
}
This code stops your script from completely finishing. sleep(1) allows the script to stop and lets the server rest for 1 millisecond, before it loops back through. You can adjust the sleep time based on your needs. In php the amount of time the script sleeps is not counted agains your server timeout time.
You'll obviously need to make more checks for you code. You'll probably also want to allow for an abort script call. Something like sending a get request to kill the backend script. Maybe on the javascript unload event.
In the tests that I've done. I made the initial ajax call, and when the value was returned, I made another ajax call, that way your back end script wont time out.
I've only played around with this on my local server, so i'm not sure how real world this is, but it works.

Categories

Resources