javascript可以将异步代码组合成一个函数吗?

时间:2012-05-23 00:21:37

标签: javascript asynchronous

在异步编程中,我们使用了很多回调,如下所示:

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

我觉得事情应该是这样的:

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

我该怎么做?

并且有一个项目:https://github.com/JeffreyZhao/jscex

我觉得这个项目不是那么容易使用(实现是通过解析源代码)

也许在将来,我们对此有一个原生的javascript支持?


我对此做了一些研究,发现了一些讨论和库,供参考:

https://github.com/JeffreyZhao/jscex

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

合并到coffeescript: https://github.com/jashkenas/coffee-script/issues/350

tamejs图书馆 http://tamejs.org/

stratifiedjs http://onilabs.com/stratifiedjs

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

关于此的维基页面: http://en.wikipedia.org/wiki/Continuation-passing_style


添加库来支持它不是一件容易的事,

也许将来,javascript会添加一个“defer”关键字。


同样的问题:Pattern for wrapping an Asynchronous JavaScript function to make it synchronous

4 个答案:

答案 0 :(得分:1)

回调是Javascript的重要组成部分。 Javascript旨在利用它们。我认为我们不会得到某种“同步器”。相反,我们正在获得越来越多的异步工具,比如Worker s。

如果您对所有这些回调感到困惑,您最好尽快习惯它们。你会没事的,相信我。

无论如何,AJAX请求可以同步完成,但请记住,这会停止执行脚本。

答案 1 :(得分:1)

您可以查看Promises。有一些可用的实现,请参阅commonjs.org。所有这些都允许链接,因此您可以按如下方式编写代码:

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
}

如果你使用jQuery,这已经内置了deferred functionality(不是我最喜欢的Promise实现):

function running(){
    do_sth();
    return $.post("/xxx")
      .then(do_sth2)
      .then(function(){ 
        $.get("/ttt")
          .then(do_sth3);
      });
}

答案 2 :(得分:1)

我确信你明白这种异步回调行为是设计上的,而不是一些不幸的疏忽。这是Node.js社区中出现的很多东西(Node使用类似的事件循环),并且已经基于光纤,线程等开发了许多替代方案。最近的一些讨论是{{3} }和here,其中也涵盖了许多替代方案。

节点论坛上的异步库上的

编辑 here,包括讨论

  • Another topic - 异步控制流程,一些功能性糖
  • async - 异步控制流程,一些功能性糖
  • after - 简单的流程控制

一些贡献者写了那些/写过其他流控制库,我肯定发现它值得一试。

我最近读过的其他内容

我不确定这是一条我要走的路,除非你特别需要这种行为(例如@MaxArt提到的浏览器中的工作人员,或者你的代码特别适合多线程(等)模型)因为大多数这些解决方案实际上是下面的单螺纹环。您可以通过传递/调用命名函数来避免过多讨厌的嵌套,例如

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

function b(val) { ... }

答案 3 :(得分:0)

由于JavaScript完全是单线程的,因此绝对无法同步异步代码。

我建议你练习掌握一切。也许你可以尝试setTimeout功能。给它一个回调,并可能在控制台上显示"Hello, World!"。并且,将数字0作为最后一个参数传递。

然而,据说,你可以借助库来“美化”异步代码。

有一个特别是我最喜欢的。它叫做async.js。我一直使用它来保持深度嵌套的异步调用看起来更加同步(即MongoDB查询)。

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.