Only pass to then, if axios request is not cancelled? - javascript

I have an axios call that I cancel, this is then caught using catch to display a message.
After this, I have chained a then(), but then() is called even if I cancel the request.
How can I make it so that then() is called only if the request is not cancelled?

Your question is hard to answer without much context. But if I understand you correctly I think what you are looking for is to delay the axios request and wait a few seconds to ensure it hasn't been cancelled before sending the request. This is called a concurrency method. Using setTimeout() will wait a certain amount of time before running any code inside of it. It is also very good to ensure users do not spam requests to your end point and wait for the newest and most recent request and return that back (if you decide to wrap your whole request in a timeout):
return axios.get('your-end-point').then(response => setTimeout(response, 1000)));
Note: 1000 here is 1000 m/s. You can change this value to be longer or shorter depending on how long you wish to wait for.
See more about setTimeout and concurrency here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

Related

is $ajax() call with a successcallback really asynchronous

I am kind of confused right now. I have the following asynchronous ajax call where I am passing a successcallback.
ajax('PUT', 'some URL', successCallback, data);
I observe that this callback is called when the request completes so I fail to understand how this call is asynchronous if it waits for the call to complete.
If I do not pass the successcallback to ajax and return the callback from the function I can observe asynchronous behavior as expected
ajax('PUT', 'some URL', undefined, data);
return successcallback();
With above change I actually observe the ajax call executing asynchronously and my page can proceed but if the page redirects to some other link the the request gets cancelled. So the only option that works is passing in succesCallback for ajax but it seems to be syncronous rather than asynchronous
I think you have your terminology backwards. "Asynchronous" in this context means "runs at some future point in time and doesn't block immediate execution of code". "Synchronous" is a blocking call, one that will halt execution until it's complete.
The callback there is intended to be executed when the request is complete, which is by definition "asynchronous". Your alternate version runs the success callback regardless, and it does that long before the AJAX call is initiated as well as not knowing if it will succeed.
You need to do asynchronous calls otherwise the JavaScript code and engine are completely jammed waiting for a response. This used to be acceptable when this is a separate process with no other responsibilities, but it's a disaster in a web application where your code likely has other things it has to respond to.

Jquery async call not working on user event

In my webpage many on-load ajax call those works fine.
Action takes time as per processing time. Means if any action that has been complete will send response and will not wait for first to finish.
But if same I am trying to do with on-lick or any user event. All ajax call works synchronously. I want these should not wait to finish the execution of first running action. All should start and complete independently.
I am using jquery 1.8 where default async= true;
Please help me here to resolve this.
Issue may be due to session lock.
more detail you can find it here
http://php.net/manual/en/function.session-write-close.php
call session_write_close function if there no session write activity in your script or function.
Such issues are observed in many concurrent ajax call and previous call has some session write activity. In this case session will be locked until it completed its execution.
If you set async to true, they will all fire at the same time.
make explicitly declaration of async = true option in each ajax call .
Useful jsfiddle link
http://jsfiddle.net/jquerybyexample/tS349/

state of XMLHttpRequest Object in jquery AJAX

In traditional javascript AJAX, we know if readystate is:
0 - The request is not initialized
1- The request has been set up
2 - The request has been sent
3 - The request is in process
4 - The request is complete.
When it comes to jQuery AJAX, we have:
complete property where we code what should happen after completion
success property where we code what should happen if the ajax request succeeds and
error property where we code what should happen if ajax request fails.
All of the above properties lets us code to do something after completion of ajax request. Where can I specify some code to execute something during processing(when readyState is 3) in Jquery Ajax??
As my AJAX script takes too long time to execute, which means, I will not attain 'complete' stage quickly. This seems like nothing is happening to the user. I wanted to initiate another ajax script at processing stage which gets information from server meanwhile and shows the user what has been done so far. Is it possible at all in Javascript? I know there is no multi-threading in Javascript.
I think I made my self clear. But, Please let me know if anything is not making any sense.
I handle this by initiating the first long running request, returning to the user immediately and allowing the process to fork server side for the extended processing.
The initial return ajax call to the user sets them up to 'watch' that process via a flag against the object ( I store them against the object in the database, but you could for instance watch file sizes or other stuff )
Subsequent ajax calls occur in a loop, each one returning setTimeout for the next call, and report on changes to that flag so the progress of the long running process is then visible. Completion of the long running process prompts NOT sending another setTimeout() and showing the overall results.
If your process is not that intensive, a simple spinner would probably do the job and no work for your server process. I usually handle that having $.ajax flip the visibility of a 'spinner' icon that's preloaded on my pages in the same spot for all.
According to jQuery's Ajax documention, they do not expose the readystate change event:
No onreadystatechange mechanism is provided, however, since success,
error, complete and statusCode cover all conceivable requirements.
It would be possible to show a loading image after the initial Ajax request is kicked off (and before getting any "complete" or "success" events, and then start polling a different URL via ajax which will give you the status of the first request, assuming your server can show progress of the long process before it completes.

setTimeout for XHR requests

quoting MDC:
If there is a possibility that your logic could take longer to execute than the interval time, it is recommended that you recursively call a named function using window.setTimeout. For example, if using setInterval to poll a remote server every 5 seconds, network latency, an unresponsive server, and a host of other issues could prevent the request from completing in its alloted time. As such, you may find yourself with queued up XHR requests that won't necessarily return in order.
For such cases, a recursive setTimeout pattern is preferred:
(function loop(){
setTimeout(function(){
// logic here
// recurse
loop();
}, 1000);
})();
In the above snippet, a named function loop is declared and is immediately executed. loop is recursively called inside setTimeout after the logic has completed executing. While this pattern does not guarantee execution on a fixed interval, it does guarantee that the previous interval has completed before recursing.
I don't understand how this fixes the problem. Shouldn't I call loop() from inside the XHR callback and not from setTimeout?
The original problem is related to setInterval(): it's possible for two or more AJAX requests to be sent before the reply to the first one is received (depending on the network latency and the timer delay). If that happens, their respective callbacks are not guaranteed to be called in order.
The solution is to delay each request independently with setTimeout() and only schedule the next request after the current request has returned (i.e. in that request's callback).
So, you're absolutely right: calling setTimeout() (through loop()) from the delayed function itself only reimplements a poorer setInterval(). You indeed have to call loop() from the AJAX callback to obtain the expected behavior.
The issue at hand is not executing single XHR request but rather repeatedly sending requests to the server at regular intervals.
Suppose you want to poll the server every five seconds and parse the response. You will just use setInterval() for this, causing XHR request to be created and sent every five seconds.
Now if there is some block in traffic or server is slow/overloaded there is chance that request A is sent and the server did not finish to process it when you send request B - that's what they mean by "queued up XHR requests" as far as I understand.
The solution in my opinion is not using setInterval() at all, but rather call the "next" XHR request only from within the callback of the previous request, possibly by using the setTimeout() as well to ensure it will "wait" the proper amount of time before polling again.

JavaScript flow or execution

If I have a JS function as follows;
function testFn()
{
x.ajaxMethod(param1,JScallBackFunction); //Please do not worry about the syntax..this just indicates an external method call
alert("Line after ajaxMethod");
}
The ajaxMethod(), lets say is some kind of method defined in an external Java file (so it can be through DWR or anything) which returns some data...Point is it takes some time to execute this line of code...
Now my question is when will the alert on next line get fired (i.e. alert("Line after ajaxMethod");)
Will it wait for these 2 things to complete (ajaxMethod execution as well as JScallBackFunction)
OR
It will be fired immediately without waiting for any of the above 2 things to complete ?
Also if you could guide in general about the JavaScript method flow execution, that will be great.
It depends. Ajax calls are usually asynchronous which means the execution of code will not be paused until the asynchronous function returns. Therefore the alert will be executed immediately.
Asynchronous functions in javascript are usually to do with Ajax and loading something from a remote server. If you do wish to force JavaScript to wait while loading that content then you can set a flag for the XMLHTTPRequest object.
this is a good question to read: When is JavaScript synchronous?
it will fire immediately after the ajax call. if you want it to wait put it in the callback function.
edit: a method that defines a callback is essentially this:
function(param1, callback) {
// do stuff
callback(); // execute callback
}
First, when you say
The ajaxMethod(), lets say is some
kind of method defined in an external
Java file
I suppose you really mean external JavaScript file.
When you send an Ajax request, you ask the browser to send a request to the server for you.
This request on the server may take sometime and you don't want to "wait" on it. (This is the whole idea of Async requests - stuff in the background).
So you tell the browser, here send this request to the server. Don't bother me unless the server responds, and once the server responds (we have a "response"), call this method. This is called callback. The method is called at a later point, when the response comes.
So the statement
x.ajaxMethod(param1,JScallBackFunction);
(assuming that it does gets a XmlHttpRequest, initializes it and calls the send method on it*) actually does two things:
Sends the Ajax request
Registers a call back function that will be called when the server responds (when we have an response). JScallBackFunction will be called when there is an response from the server.
But since this is an asynchronous request, the browser does not "wait" instead it continues to the next statement (if there is one) after the Ajax call and executes it.
So, alert("Line after ajaxMethod"); will be executed immediately.
*If this does not make any sense for you, this is how an Ajax request is actually "created" and "sent". This article may help you understand.

Categories