I have an object which acts as a client side API Client which exposes several functions which all return jQuery ajax() objects. Some of those ajax calls have .done() and .fail() calls chained directly onto them because they are actions which need to be taken every time the API responses come back before the rest of the js code is allowed to deal with the response. Pretty standard stuff.
I need to kick off a variable number of API requests, wait for all to fail or succeed, and then continue processing. For the examples I will create, I will simplify this down to just two ajax calls.
So I create an array to hold the returned ajax objects, and then use $.when().apply(null, deferreds).then(function(){//do something after both ajax requests complete}). When the calls complete successfully, everything works great. When calls fail (such as if the ajax call 404s), things are not so great.
The problem is that .then() doesn't seem to detect the fails, even though I thought then() was supposed to be fired regardless of success or failure of the underlying promise(s).
I can switch to .always(), which seems to work better (in that it detects the failures and still triggers the callback) but it seems to fire before some of the .fail() callbacks that are registered directly on the ajax calls, which doesn't make sense to me since I thought the callbacks for an ajax call were called in the order they were registered.
I'm sure I'm just missing something about the behavior of the ajax() when() then() combo.
Fiddle showing successful calls using .then(): https://jsfiddle.net/kwrLyw6q/5/
Fiddle using .then() with failed ajax calls (not working, would love to know why. Seems like this is the "right" way to do it, but I can't figure out where I'm going wrong): https://jsfiddle.net/kwrLyw6q/2/
Fiddle using .always() (working, but notice the out-of-order callback order. At least, out of order compared to the order I want them!): https://jsfiddle.net/kwrLyw6q/7/
It looks like deferred.then() takes three arguments:
success function (first argument).
fail function (second argument).
progress function (third)
updated fiddle
Related
For a couple of years, I was dealing with a part time problem where some DOM elements loaded with jquery html function were not accessible immediately after the function call (The behaviour was a bit like executing a function without waiting for the document ready event). Even though .html() is suppose to be synchronous, this SO answer (and also this one) suggests using the promise of the html function:
$('#divId').html("<h1>hello</h1>").promise().done(function(){
//Callback
});
A promise could make sense in such context but what intrigues me about this promise is that it will also be returned with every jquery's object:
$('#divId').promise().done(function(){
//Will also be called...
});
Since I couldn't find anything about it in the documentation of the html function, I was wondering what was the real purpose of this promise and if it is used correctly in this context.
The two methods are not related. The reason people often suggest this is because someone found out that they could use .promise().done() to make their code that has a race condition work. It worked for the same reason wrapping the same code in setTimeout(fn, 0) would make it work; it pushes it off to the callback queue to be ran later, likely after the browser performs a render or after some other async callback completes.
.html is synchronous, does not have a callback, and does not need a callback. However, the browser's renderer is asynchronous, so it won't render the change until after the callstack is clear. Using .promise pushes the callback off to the callback queue, thus running the code after a render which resolves the race condition or async logic flaw.
.promise() used on a jquery collection returns a promise that will resolve once all currently running jquery animations are complete. If there are no currently running animations, the promise will resolve immediately and the callback will be pushed to the callback queue to be called once the stack is clear.
It's nothing more than a bandaid. I'd suggest not using it, and instead fixing whatever async logic flaw is causing it to be the solution.
I have a number of async calls being made in JavaScript. I would like to ensure that only a single async call is in flight at any one time. How can I achieve this?
Does the Q library expose something relevant to this?
It depends if you want to retain all calls or discard any calls made while one is in-flight.
If you want to retain all calls, you shouldn't make the Ajax calls directly, but rather put them in a queue. The queue abstraction would then be responsible for making the Ajax calls, using a lock variable to check if one is already in-flight. When an Ajax call is received or timed out, it can trigger the queue to check for any pending calls so the next one can be fired off.
If you want to discard calls made while one is in-flight, a simple lock mechanism would do. For any call, just check if the lock is true and if not, fire the request and set the lock to true. If the lock is true, do nothing (discard it). Clear the lock when the call is received or times out.
I'm not a Q user, but Q is essentially a library implementing promises, so you can ensure this by chaining a series of .then clauses together, each one containing one call, or launching the next call from the .done operation of the previous AJAX call.
What i can think of is using a functions queue to process ajax functions based on the result of jQuery.active which counts the active ashync calls.
So when calling an ajax function check for the active ajax running, if it is 1 then add your function to the queue, other wise execute it.
You can then use the ajaxStop function to trigger any remaining function to be called within the queue, call the function and remove it from queue.
In this way you will ensure that a single ajax call runs. This is just some brainstorming, I haven't tested the exact behavior but this approach might help.
Learnyounode is a commandline based learn-by-doing-and-getting-your-results-tested tutorial for javascript's node
In the seventh tutorial, the idea is to make something of a http client using node.js's http's get function.
The get function has two arguments
the url
a callback function for the asynchronous job
So I scourgd the surface of the internet looking for a way to continously accept data till the operation ended. After a while seeing that every answer was pretty much along the lines of
function callback(res){
res.on("data",function (data) { console.log(data.toString());})
}
http.get(url,callback)
I thought maybe failing the inbuilt tests would give me a clue to see how to make multiple calls but weirdly enough it passed the multiple calls test.So I thought the test called the file and hence the function, multiple times .. but after some tries..I realised that wasn't the case.
So my question : what exactly goes on behind a async call ? how is it possible for the mechanism to call it more than once? What other surprises should I expect ? to me this is taking black box thinking to a whole new level and I place it on par with thinking about list monads atm.
I think the key point is to understand that res is an EventEmitter (IncomingMessage to be more accurate), so what does the function named callback (only once on the response event of the httpClientRequest object you create when calling http.get()) is to attach an event listener to the data event of res. Without going into details, to optimise data flow, when you receive some data bytes from the network a buffer is filled and when is full the event 'data' is triggered so you can process the incoming chunk. Hence the callback you have set to the data event is executed on every chunk of data coming from the network
I am calling a third party webservice using getJSON callback. The function does not have a success handler attached to the function and since it is third party, I cannot edit the code also. By the time I receive the response, some of the javascript function in the page already executes.
Is there any way I can delay the execution of the Javascript function till I receive the response data from web service except setTimeout method.
Description
You can use jQuery's .ajaxStart() and .ajaxComplete() events to get noticed if your ajax call is running. You can create a bool variable, something like isAjaxRunning and put this around the other javascript. So if isAjaxRunning is true, dont execute other javascript.
More Information
jQuery.ajaxStart()
jQuery.ajaxComplete()
if you have access to the code you can make it synchonize by adding the attribute
async : false
- then it won't be a asynchronous call like the normal ajax .
If you can post the sample code - that will give a clear picture.
I have a few questions on jQuery AJAX.
It is confusing to understand why there are multiple methods like load(), get(), post()..is the diff only like $.ajax is general way of writing and others being specific based on type..?
I do not cleatly understand the diff between complete, success..Are they similar or is there any diff as to when each should be used ?
In terms of script execution from within an HTML response, does jQuery AJAX handle it automatically OR do we need to specify something like eval() ? Also how diff is this behavior compared to a normal AJAX only handling?
Regarding the beforeSend , is it similar to ajaxSetup and generally speaking, what are the common attributes which are used out of the many which are availbale?
Edited
Also is the code written as callback for load()..e.g. load(url,function(){});
same as what is mentioned under success or ajaxSuccess..I mean will the callback function code not exectuted at the same time as the success or ajaxSuccess ?
Thnak you.
1) you need to understand HTTP. get and post make "GET" and "POST" requests, respectively, which is useful if you are building a RESTful service. EDIT: I actually don't see get and post methods on the ajax object; you pass a 'type' parameter to specify the HTTP method you want to use.
2) success fires on success, i.e. if the response returns a 200. complete always fires after everything else is done.
3) Ideally, your server would return json. If you configure the Ajax call to expect json, then it will parse it for you.
4) The documentation is very clear, beforeSend is fired before the actual underlying ajax request is invoked. The documentation says things like "Use this to set custom headers, etc."
They are just "shorthand"
everything can be done and function
the exact same with $.ajax(), the
difference is only syntax
complete is fired after every request is complete, while success only fires if there were no errors (a successfully one
whatever you want to do with the HTTP response you do by making a function(data){dostuff(data);} in the success callback area
beforeSend is called right before the ajax request is fired
Documentation