linjunhalida
linjunhalida

Reputation: 4655

Can javascript combile async code into one function?

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

Upvotes: 1

Views: 394

Answers (4)

meloncholy
meloncholy

Reputation: 2192

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) { ... }

Upvotes: 1

Sal Rahman
Sal Rahman

Reputation: 4748

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.

Upvotes: 0

Bergi
Bergi

Reputation: 664317

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);
      });
}

Upvotes: 1

MaxArt
MaxArt

Reputation: 22617

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.

Upvotes: 1

Related Questions