Guaranteeing asynchronous request callback order in Javascript - javascript

In Javascript, I have two asychronous requests for data:
$.getJSON('http://foo.com', fooQuery, fooSuccess(data));
$.getJSON('http://bar.com', barQuery, barSuccess(data));
and two callbacks to process the received data:
fooSuccess(data) { // Stuff }
barSuccess(data) { // More Stuff }
How do I ensure barSuccess is executed only after fooSuccess completes?
Notes:
I want to keep the data requests as they are: asynchronous and non-blocking (since server responses may take a while).
But, I want the callbacks that process the data to be executed sequentially. That is, I do not want to execute barSuccess until fooSuccess completes.
Thanks so much for your wisdom and help!

Here is how you would do it using the jQuery deferred object that is returned by ajax requests.
var fooDfd = $.getJSON('http://foo.com', fooQuery);
var barDfd = $.getJSON('http://bar.com', barQuery);
fooDfd.then(function(fooData){
fooSuccess(fooData);
barDfd.then(barSuccess);
});
​

The best way would be to utilize the jQuery when().done() functionality like this:
$.when(
$.getJSON('http://foo.com', fooQuery, fooSuccess(data)),
$.getJSON('http://bar.com', barQuery, barSuccess(data))
).done(function(arg1, arg2){
fooSuccess(arg1);
barSuccess(arg2);
});
This allow simultaneous execution of the AJAX requests and guaranteed execution of the done() function once all requests has successfully completed.

I'm follow this very interesting post from a half an hour ago, when appear the elegant solution presented by #Mike Brant I quickly was to dive in the jquery library to see how the magic is made. Don't you? I recommend, is very interesting!
BTW I think we don't need all that magic, not in this case, we have two asynchronous calls handlers(functions), no matter which end first, we need to know when the second end, then all we need is a third function that will be called by the two handlers and act when all the data is ready. I know this approach will vaste four or five lines more of code than the elegant jquery solution, but at the end our brain and soul will be in better condition. Sorry my english.

Put the barSuccess call in the fooSuccess success callback.
fooSuccess(data){
jQuery.ajax({
data: data,
success: function(response){
barSuccess(data) //should still be in scope, I think?
}
}
}

Related

continue in js program after finishing ajax calls

I have a function with 3 ajax calls
var loadEditModalAddressData(){
loadCountries();
loadStates();
loadDistricts();
};
I want from js to wait, until all ajax calls are finished.
Part of my code
loadEditModalAddressData();
$(document).ajaxStop(function(){
// functionality using requested data
....
}
This worked fine, until I added extra features and figured out that $(document).ajaxStop is called after every complete request(or bunch of requests),not only in certain function scope, which mash up my code functionality.
How do I do that?
The dirty way could be to use a counter in ajaxStop to make sure all three calls have returned. A slightly better way could be to add callbacks to each of your calls and to launch the treatment when the last is received.
However, the best way is probably to use promises.
If you use jQuery to do your calls, you can do stuff like:
$.when(call1, call2, call3).then(function(results){
// your stuffs
});
Where the callX are what returns $.get (or any other jQuery promise).
Have a look here.
Use $.when to wait for multiple defereds/promises. It's synonymous to the native Promise.all().

Is asnyc : false really that bad?

My question consists of two parts.
In my webpage, i am creating some of my divs dynamically using ajax post calls to get some information from db. Then i create my divs. My structure is as follows.
<html>
<body>
<script type="text/javascript" src="some.js"></script>
<script type="text/javascript" src="createDivs.js"></script>
<script type="text/javascript" src="useThatDivs.js"></script>
<script type="text/javascript" src="useThatDivsMore.js"></script>
</body>
</html>
Here, createDivs.js does the ajax call with async:false (because on later scripts, i use these divs)(and btw, it is a post call to the server), and gets the info from db, then create the divs according to the info.
So my questions are.
1) Does ajax calls should always be async? Then, my usage of ajax is
completely useless/wrong here?
2) If async:false is dreprecated, what should i use instead of this
approach?
If you want a better solution i think you should look in to javascript promises. Q.js is a good place to start.
Nobody prefers to use a UI that frequently goes unresponsive for 1-3 seconds. They would much prefer to use a web-site that stays alive, even as they do things. Really it's as simple as that.
It takes a little more work to design for async Ajax calls, but it generates a better user experience. And, once you learn how and take advantage of tools available, it's not hard at all, just different than synchronous programming.
Since you've tagged your question with jQuery, you have jQuery's Ajax support available to you and every jQuery Ajax call returns a promise. Promises can make async programming work more like (though not identical to) synchronous programming. You can write something like:
$.ajax(...).then(function(data) {
// process results here
});
If you want to sequence several asynchronous operations, you can even chain promises.
$.ajax(...).then(function(data) {
// process results here
// kick off next ajax call
return $.ajax(...);
}).then(function(data) {
// process results of 2nd ajax call
});
Or, if you want to launch three parallel async operations (for better performance) and then do something when all three finish, you can do this:
$.when($.ajax(...), $.ajax(...), $.ajax(...)).then(function(data1, data2, data3) {
// process results of all three ajax calls here
});
Oh, and if you want to use things like JSONP to do cross domain Ajax/JSON, you can ONLY use async.
Use callbacks of AJAX success and error. If you are using synchronous AJAX calls, than you are locking all interfaces of your website, till all responses are done.
$.ajax({
url: '#',
data: {id: 1},
success: function(dataFromServer) {
callFunctionToProcess(dataFromServer);
/* OR */
var directlyProcess = dataFromServer;
},
error function(data) {
var yourRequestHasFailed = true; // e.g. you get 500 server error
}
});
EDIT FOR jfriend00
It will not lock any other tabs of your browser, as it will not lock any of the following: OS, BIOS, house doors, car doors or any other lockable item.

forcing synchronous javascript using closures

This code hangs.
I am reasonably sure it's because the response in the anonymous function is a new variable not connected with the outer scope. How do I solve this?
function foo() { //...
var url = "http://urliciously-urlish-url"
response = null;
$.get(url, function (data) {response = data;
});
while( response === null)
{
1;
}
console.log(response);
//...
}
Note I am aware that this design will (as usual for polling systems) hang the page until response becomes non-null. That's OK in this context.
$.get is asynchronous. If you really want this to be synchronous, you'll have to use the $.ajax function:
$.ajax({
url: url,
async: false,
success: function(data) {
response = data;
}
});
That being said, I agree with cHao -- you should get used to writing asynchronous code.
While your code is running, the event handlers won't.
Translation: This code won't work.
If you want to use JS, you'll almost definitely have to get used to writing asynchronous code.
No, the problem is that the callback will never be executed because the JS thread is still running. It will wait for the current context to be ended, before it goes on executing the "next tick" (the callback here). Between the ticks it may also update DOM and handle other things.
Instead of using a hanging loop, use a synchronous ajax request (yes, thats possible). In jQuery: {async:false}. However, it then will "only" hang until the request is ended - which maybe never happens. And unresponsable GUI is the worst thing to happen, so DO NOT USE it.

What's the most efficient way to wait for an asynchronous function call in Javascript?

This might be the opposite of my previous question here but anyway, I need to know its answer as well.
I have an Ajax call in my algorithm that I need to wait for it to run some code. There are two solutions:
1) The typical solution:
ajaxCall(function(result){
//the code to run after the call is returned
});
2) The one I'm wondering if it can be an alternative:
res=null;
ajaxCall(function(result){
res=result;
});
while(res==null)/*wait! but this will lock the GUI I guess*/;
//do the rest of the code because now res is initialized
The question is how can I write the second solution in an efficient way that doesn't freeze the GUI?
Just make the ajax call synchronous.
ref: http://developer.mozilla.org/en/XMLHttpRequest
look for the async parameter
I suggest hooking all dependent code to execute as a callback from your ajax call 's return. That way, all other javascript can continue to execute and you will not make your browser unresponsive for the duration of the call.
Alternatively, which is not something I would never ever do, you can make your ajax call synchronous, using async: false like so:
$.ajax({ url: ..., async: false });
A generic answer:
There are only two methods available in async. programming: events and callbacks. Period.
(Technically speaking, there is not really a difference between the two on the lowest level, an "event" is just a (library) function - the one doing the event "firing" - executing all functions registered as listeners so it's the same as a callback - technically, i.e. when you write event.fire() or whatever the event syntax of your preferred lib it's synchronous invocation of all registered event handler functions). When to use one or the other is a matter of preference, convention and style when designing an API.)
Javascript programming, especially AJAX, is asynchronous by definition. So if you have an algorithm that needs to "wait" for something, you're better off reconsidering the algorithm. Ironically enough, Javascript syntax is not best suitable for async programming, but there are many libraries that help you keep callbacks under control and avoid spaghetti code.
Example of callbacks spaghetti:
function ajaxRequest(url1, function() {
animateSomething(div, function() {
ajaxRequest(url2, function() {
....
})
})
})
the same with async.js looks much cleaner:
async.series([
function(_) { ajaxRequest(url1, _) },
function(_) { animateSomething(div, _) },
function(_) { ajaxRequest(url2, _) }
])
there are many ways to do this one. one of the is passing a callback to the ajax (or at least a reference of it). your code #1 would be an example of that.
another is that you have a notifier object which you add the ajax success call to it. then you can have other functions (one or more) plug into it to listen for a "success" announcement.

Pattern for wrapping an Asynchronous JavaScript function to make it synchronous

I'm working with a JavaScript API where most of the functions are asynchronous. The API is the WebKit JavaScript Database API which is a binding to a subset of functionality to manipulate SQLite3 databases. I understand the design decision to make things async as to not block and provide a responsive user interface. In my situation I know that my usage of the async API calls will execute fast. Since this is the case I'd like to provide my developers a cleaner and easier to use wrapper API that forces synchronous calls.
Here's the async call
db.executeSql(sqlStatement, function(result) {
// do something with result
});
And here's what I'd like to be able to do
var result = dbWrapper.executeSql(sqlStatement);
// do something with result
Is there a design pattern/way to do this? A written or linked to code example is preferred. The target platform/broswer is Mobile Safari on the iPhone.
Thank you
Sorry, JavaScript does not provide the language primitives (eg. threads or coroutines) to make asynchronous things act synchronously or vice-versa.
You generally* get one thread of execution only, so you can't get a callback from a timer or XMLHttpRequest readystatechange until the stack of calls leading to the creation of the request has completely unravelled.
So in short, you can't really do it; the approach with nested closures on the WebKit page you linked is the only way I know of to make the code readable in this situation.
*: except in some obscure situations which wouldn't help you and are generally considered bugs
StratifiedJS allows you to do exactly that.
There's even an article on how to apply it on browser storage:
http://onilabs.com/blog/stratifying-asynchronous-storage
And this is the Stratified JavaScript library it uses https://gist.github.com/613526
The example goes like:
var db = require("webdatabase").openDatabase("CandyDB", ...);
try {
var kids = db.executeSql("SELECT * FROM kids").rows;
db.executeSql("INSERT INTO kids (name) VALUES (:name);", [kids[0]]);
alert("done");
} catch(e) {
alert("something went wrong");
}
maybe a bit late, but the tech didn't exist back then ;)
You can try something like:
function synch()
{
var done = false;
var returnVal = undefined;
// asynch takes a callback method
// that is called when done
asynch(function(data) {
returnVal = data;
done = true;
});
while (done == false) {};
return returnVal;
}
But that may freeze your browser for the duration of the asynch method...
Or take a look at Narrative JavaScript: Narrative JavaScript is a small extension to the JavaScript language that enables blocking capabilities for asynchronous event callbacks. This makes asynchronous code refreshingly readable and comprehensible.
http://neilmix.com/narrativejs/doc/index.html
Mike
if you are using jQuery Ajax :
$.ajax()
you can set the attribute of asynch to false ,
and then you will have a synch ajax request to the server.
We are using GWT RPC which also has an async API. The solution that we are currently using to make several async calls in serial is call chaining:
callA(function(resultA) {
callB(resultA, function(resultB) {
callC(); //etc.
});
});
This nested approach achieves what you want but it is verbose and hard to read for newcomers. One of the approaches that we have investigated is adding the calls that we need to make to a stack and executing them in order:
callStack = [
callA(),
callB(),
callC()
];
callStack.execute();
Then the callstack would manage:
Invoking the calls in serial (i.e. the wiring in the first example)
Passing the result from one call forward to the next.
However, because Java doesn't have function references, each call on the call stack would require an anonymous class so we stopped short of such a solution. However, you may have more success in javascript.
Good luck!
This doesn't actually implement synchronous operation of the db query, but this was my solution for easy management. Basically use the calling function as the callback function, and test for the results argument. If the function receives results, it parses them, if not, it sends itself as a callback to the query method.
render: function(queryResults){
if (typeof queryResults != 'undefined'){
console.log('Query completed!');
//do what you will with the results (check for query errors here)
} else {
console.log('Beginning query...');
this.db.read(this.render); //db.read is my wrapper method for the sql db, and I'm sending this render method as the callback.
}
}
I am not sure if this is the right place but I cam here searching for answers to making an synchronous calls in Firefox. the solution would be to remove onreadystatechange callback and do a direct call.
This is what I had found and my solution
synchronous call back with rest service

Categories