I am calling one cgi script which takes 50 minutes to send response.I need to keep my xhr alive till the response comes from that cgi.
How to do that ?
it seems like after certain default time request automatically timed out.
You can use:
xhr.timeout = 10000;
xhr.ontimeout = timeoutFired;
for this purpose
I don't think you should be doing this inline with the request. The alternative is to submit your request as a job to some back end process/thread/message queue and store a reference so that you can access the results, e.g. in a database or even a file once the processing is complete.
Until the results are available, you could show some 'updating' text or spinning icon to let the user know something is happening.
For that length of time I wouldn't rely on an open HTTP connection.
Related
I'm trying to understand more about long polling to "manipulate" a website in real time, saw some videos and I'm thinking so far:
Say I have an old date that the sql and I make an echo on it. As long polling will know if the old date will not be the same as it will look from time to time according to the setInterval function ...?
Say I want to show publication of a blog in which all text is in mysql, but repende I publish a new publication, and who is on the page at the time, you will see the publication time (not tell me?), Then how one long polling code will know the difference between the old and the new publication? Ate even not to give conflicting or repeating the same date engraved on the sql.
Since your initial question was what the difference between the two techniques is, I will start with this:
AJAX polling
Using AJAX polling to update a page will mean, that you send a request in a defined interval to the server, which would look like this:
The client sends a request to the server and the server responses immediately.
A simple example (using jQuery) would look like this:
setInterval(function(){
$('#myCurrentMoney').load('getCurrentMoney.php');
}, 30000);
The problem with this is, that this will cause a lot of useless requests since there won't be always new things on every request.
AJAX long polling
Using AJAX long polling will mean, that the client sends a request to the server and the server waits for new data to be available before he responds. This would look like this:
The client sends a request and the server responds "irregularly". As soon as the server responds, the client will send a new request to the server.
The client side would look like this:
refresh = function() {
$('#myCurrentMoney').load('getCurrentMoney.php',function(){
refresh();
});
}
$(function(){
refresh();
});
What this will do is just load the getCurrentMoney.php's output into the current money element and as soon as there is a callback, start a new request.
On the server side you usually use a loop. To solve your question how the server will know, which are new publications: either you pass the timestamp of the newest to the client available publication to the server or you use the time of the "long polling start" as indiactor:
<?
$time = time();
while ($newestPost <= $time) {
// note that this will not count as execution time on linux and you won't run into the 30 seconds timeout - if you wan't to be save you can use a for loop instead of the while
sleep(10000);
// getLatestPostTimestamp() should do a SELECT in your DB and get the timestamp of the latest post
$newestPost = getLatestPostTimestamp();
}
// output whatever you wan't to give back to the client
echo "There are new posts available";
Here we won't have "useless" requests.
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
When I type text into my textfield widget I send request with every character typed into it to get matching data from the server.
When I type really fast I swarm server with the requests and this causes to freeze my control, I managed to create throttling mechanism where I set how many ms client should wait before sending request. This requires to set arbitrary constant ms to wait. The better solution would be to just cancel sending previous request when the next key button is pressed.
Is it possible to cancel AJAX request independently of its current state? If yes, how to achieve this?
Call XMLHttpRequest.abort()
See: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/abort
You'll have to track your requests somehow, perhaps in an array.
requests = [];
xhr = new XMLHttpRequest(),
method = "GET",
url = "https://developer.mozilla.org/";
requests.push(xhr);
MDN says :
The XMLHttpRequest.abort() method aborts the request if it has already
been sent. When a request is aborted, its readyState is set to 0
(UNSENT), but the readystatechange event is not fired.
What's important to note here is that while you will be able to .abort() requests on the client side (and thus not have to worry about the server's response), you are still swarming your server because all those requests are still being sent.
My opinion is that you had it right the first time, by implementing a mechanism that limits the frequency of AJAX requests. You mentioned that you had a problem with this freezing your control (I assume you mean that the browser is either taking longer to respond to user actions, or stops responding completely), and this could be a sign that there is a problem with the way your application handles asynchronous code.
Make sure you are using async APIs like Promise correctly, avoid loops that do heavy processing or just wait around in client code, and make your event processing (i.e your AJAX callback) simple and fast to reduce the impact on the user.
I have a JavaScript application that regularly saves new and updated data. However I need it to work on slow connection as well.
Data is submitted in one single HTTP POST request. The response will return newly inserted ids for newly created records.
What I'm finding is that data submitted is fully saved, however sometimes the return result times out. The browser application therefore does not know the data has been submitted successfully and will try to save it again.
I know I can detect the timeout in the browser, but how can I make sure the data is saved correctly?
What are some good methods of handling this case?
I see from here https://dba.stackexchange.com/a/94309/2599 that I could include a pending state:
Get transaction number from server
send data, gets saved as pending on server
if pending transaction already exists, do not overwrite data, but send same results back
if success received, commit pending transaction
if error back, retry later
if timeout, retry later
However I'm looking for a simpler solution?
Really, it seems you need to get to the bottom of why the client thinks the data was not saved, but it actually was. If the issue is purely one of timing, then perhaps a client timeout just needs to be lengthened so it doesn't give up too soon or the amount of data you're sending back in the response needs to be reduced so the response comes back quicker on a slow link.
But, if you can't get rid of the problem that way, there are a bunch of possibilities to program around the issue:
The server can keep track of the last save request from each client (or a hash of such request) and if it sees a duplicate save request come in from the same client, then it can simply return something like "already-saved".
The code flow in the server can be modified so that a small response is sent back to the client immediately after the database operation has committed (no delays for any other types of back-end operations), thus lessening the chance that the client would timeout after the data has been saved.
The client can coin a unique ID for each save request and if the server sees the same saveID being used on multiple requests, then it can know that the client thinks it is just trying to save this data again.
After any type of failure, before retrying, the client can query the server to see if the previous save attempt succeeded or failed.
You can have multiple retries count as a simple global int.
You can also automatically retry, but this isn't good for an auto save app.
A third option is use the auto-save plugins for jQuery.
Few suggestions
Increase the time out, don't handle timeout as success.
You can flush output of each record as soon as you get using ob_flush and flush.
Since you are making request in regular interval. Check for connection_aborted method on each API call, if client has disconnected you can save the response in temp file and on next request you can append the last response with new response but this method is more resource consuming.
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.