Asynchronous JavaScript programming without messy callbacks

I want to turn an asynchronous function into a synchronous one.

function fetch() { var result = 'snap!'; $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function messyCallback(data){ result = data; }); return result; } document.write(fetch());โ€‹ 

See in action

The result will always be โ€œsnap!โ€ Because $.getJSON is executed after fetch() .

My first idea:

 function fetch() { var result = 'snap!'; $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function messyCallback(data){ result = data; }); while (true) { if (result != 'snap!') return result; } } 

This does not work, and also disables the browser.

I read about generators and iterators in JS 1.7 , but I have no idea how to apply it to my problem.

This question is not really about jQuery. Instead of $. GetJSON can be any other asynchronous function.

+7
javascript synchronization asynchronous callback
source share
6 answers

See also this question: Stop JavaScript without blocking the browser

Doing exactly what you want does not work. You cannot create synchronization from asynchrony (just the opposite) in a single-threaded event-driven environment. You have to accept the asynchronous nature of the language and develop your own consistent style of callback handling so that your code is readable / supported. For example, you can not do any real work inside a callback closure, but just call another top-level function / method for clarity.

+9
source share

You want to flip your own $ .getSyncJSON, which uses $ .ajax ({async: false}). See: http://api.jquery.com/jQuery.ajax/ .

I must advise you against this course of action. You can easily block the browser from all input by placing your user interface in the power of the web. But if you know what you are doing and are confident in your case, go for it.

+2
source share

Instead of writing helper methods, such as your fetch , that return a value, make them accept another function, the โ€œreceiverโ€, to pass their result:

 function fetch(receiver) { $.getJSON("blah...", function(data) { receiver(data); }); } 

Obviously, this is redundant, because exactly how getJSON already works, but in a more realistic example, the fetch function will process or filter the result one way or another before passing it.

Then instead of:

 document.write(fetch());โ€‹ 

You would do:

 fetch(function(result) { document.write(result); }); 

Generators can be used to make asynchronous code much more linear in style. Every time you need some kind of asynchronous result, you have to run the function to start, and the generator will resume when the result is available. There will be some control code to ensure the operation of the generator. But this does not help much, because generators are not standard for browsers.

If you're interested, write a message about using generators to remove asynchronous code .

+2
source share

There is an extension for the JavaScript language called StratifiedJS. It runs in every browser, and it allows you to do just that: processing asynchronous tasks synchronously / linearly without freezing the browser.

You can enable Stratified JavaScript, for example. by including Oni Apollo on your web page, for example:

 <script src="http://code.onilabs.com/latest/oni-apollo.js"></script> <script type="text/sjs"> your StratifiedJS code here </script> 

And your code will look like this:

 function fetch() { return require("http").jsonp( "http://api.flickr.com/services/feeds/photos_public.gne?" + "tags=cat&tagmode=any&format=json", {cbfield:"jsoncallback"}); } document.write(fetch());โ€‹ 

Or if you really want to use jQuery in StratifiedJS:

 require("jquery-binding").install(); function fetch() { var url = "http://api.flickr.com/?format=json&...&jsoncallback=?" return $.$getJSON(url); } document.write(fetch());โ€‹ 

Documents are at http://onilabs.com/docs

+2
source share

The TameJS library is designed to solve this problem.

You can write something like (untested):

 var result = 'snap!'; await { $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", defer(result)); } return result; 
+2
source share

$. The ajax () function from jQuery has more options, including async: [true|false] (default is true).

However, in most cases, you should follow Ben's advice and "embrace the asynchronous nature of the language."

+1
source share

All Articles