1

on async programming, we use lots of callbacks, like this:

var running = function(){
    do_sth();
    $.post("/xxx", function(data){
        do_sth2();
        $.get("/ttt", function(data){
            do_sth3();
        }
    }
}

and I think things should be like this:

var running = do_async(function(){
    do_sth();
    var data = $.post("/xxx");
    do_sth2();
    data = $.get("/ttt");
    do_sth3();
});

How can I do that?

and there is a project on this: https://github.com/JeffreyZhao/jscex

and I think this project is not that easy to use (implementation is by parse the source code)

maybe in the future, we have a native javascript support on this?


I did some research on this, found some disscussion and library here for reference:

https://github.com/JeffreyZhao/jscex

defer coffeescript https://github.com/jashkenas/coffee-script/issues/350

merge into coffeescript: https://github.com/jashkenas/coffee-script/issues/350

tamejs library http://tamejs.org/

stratifiedjs http://onilabs.com/stratifiedjs

kaffeine http://weepy.github.com/kaffeine/

wiki page about this: http://en.wikipedia.org/wiki/Continuation-passing_style


It is not very easy to add a library to support it,

maybe in the future, javascript will add a "defer" keyword.


same question: Pattern for wrapping an Asynchronous JavaScript function to make it synchronous

Community
  • 1
  • 1
linjunhalida
  • 4,538
  • 6
  • 44
  • 64
  • If you want execution to pause until the `$.post()` (or other async function) has completed that would be _synchronous_ code, not _async_. (Which you _can_ do, but really shouldn't.) Have you looked into using [jQuery's deferred functionality] (http://api.jquery.com/category/deferred-object/), which would at least let you structure your code a bit differently if not quite the way you want? – nnnnnn May 23 '12 at 00:39
  • I think Jscex is easy to use. It's based on compilation technology but it's designed to be transparent to the user. Could you give me your thoughts of this project? – Jeffrey Zhao Jun 07 '12 at 02:34

4 Answers4

1

Callbacks are a vital part of Javascript. Javascript is designed to make use of them. I don't think we will ever get some kind of "synchronizer". On the contrary, we're getting more and more instruments to do things asynchronously, like Workers.

If you feel puzzled by all these callbacks, you'd better get used to them ASAP. You'll be fine, believe me.

Anyway, AJAX request can be done synchronously, but keep in mind that this halts the execution of the script.

MaxArt
  • 22,200
  • 10
  • 82
  • 81
1

You might have a look into Promises. There are some implementations available, see commonjs.org. All of them allow chaining, so you can write your code as follows:

function running(){
    return do_sth()
       .then($.post.bind($, "/xxx"))
       .then(do_sth2)
       .then($.get.bind($, "/ttt"))
       .then(do_sth3);
    // returns a Promise to run all these tasks
    // ...or:  a Promise for the result of the last of the chained tasks
}

If you use jQuery, this is already built-in with the deferred functionality (not my favourite Promise implementation, though):

function running(){
    do_sth();
    return $.post("/xxx")
      .then(do_sth2)
      .then(function(){ 
        $.get("/ttt")
          .then(do_sth3);
      });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

I'm sure you appreciate that this async callback behaviour is by design, and not some unfortunate oversight. It's something that comes up quite a lot in the Node.js community (Node uses a similar event loop), and a number of alternatives have been developed there based on fibres, threads, etc. A couple of recent discussions are here and here, which also cover a number of these alternatives.

Edit: Another topic on async libraries on the Node forum, including discussion of

  • async - async control flow, some functional sugar
  • after - async control flow, some functional sugar
  • step - simple flow control

Some of the contributors wrote those / have written other flow control libraries, and I definitely found it worth checking out.

Other stuff I've read recently

I'm not sure it's a route I'd go down, though, unless you have a specific need for that sort of behaviour (e.g. workers in the browser as @MaxArt mentioned, or your code fits particularly well with a multithreaded (etc.) model) as most of these solutions are actually single threaded loops underneath. You can avoid too much nasty nesting by passing / calling named functions, e.g.

function a() {
  somethingAsync(function (val) { b(val); });
}

function b(val) { ... }
meloncholy
  • 2,122
  • 18
  • 16
  • Yes, I use this method in my code now, and I hope there is a better way to do this.. – linjunhalida May 23 '12 at 01:21
  • Good to know. :) The reason I brought up Node is that quite a few solutions have already been developed for it, so you may well be able to find something that works for you there. It's not an area I've played around with much myself, but others in the community are well versed in this sort of thing. – meloncholy May 23 '12 at 01:32
  • Read some more on this topic recently and thought I'd add it here in the hope it's useful to others too. (Hi, any others reading this!) – meloncholy May 30 '12 at 14:08
0

Since JavaScript is entirely single-threaded, there is absolutely no way that you can synchronize asynchronous code.

I recommend that you practice to get the hang of things. Maybe you could try the setTimeout function. Give it a callback and maybe make it display "Hello, World!" on the console. And also, pass in the number 0 as the last parameter.

With that said, however, you can "prettify" asynchronous code with the help of libraries.

There is one out there that is particularly my favourite. It's called async.js. I use it all the time to keep deeply nested asynchronous calls looking more synchronous (ie, MongoDB queries).

async.waterfall([

  // Call to the first asynchronous call...
  function (callback) {
    setTimeout(function () {
      callback(null, "Hello, World!");
    }, 0);
  },

  // That needs to make another...
  function (callback, message) {
    console.log(message);
    setTimeout(function () {
      callback(null, "It's a nice day!");
    }, 0);
  },

  // Another...
  function (callback, message) {
    console.log(message);
    setTimeout(function () {
      callback(null, "Bye, now!");
    }, 0);
  },

  // And another.
  function (callback, message) {
    console.log(message);
  }

]);

// Without making the entire thing hopelessly nested deeply.
Sal Rahman
  • 4,607
  • 2
  • 30
  • 43