1

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

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

推迟咖啡脚本 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

咖啡因 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

4 回答 4

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,它已经内置了延迟功能(虽然不是我最喜欢的 Promise 实现):

function running(){
    do_sth();
    return $.post("/xxx")
      .then(do_sth2)
      .then(function(){ 
        $.get("/ttt")
          .then(do_sth3);
      });
}
于 2012-05-23T00:47:32.990 回答
1

我相信您会理解这种异步回调行为是设计使然,而不是一些不幸的疏忽。这在 Node.js 社区中出现了很多(Node 使用类似的事件循环),并且已经基于纤维、线程等开发了许多替代方案。最近的一些讨论在这里这里,这也涵盖了其中一些替代方案。

编辑: Node 论坛上关于异步库的 另一个主题,包括对

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

一些贡献者编写了这些/已经编写了其他流控制库,我绝对发现它值得一试。

我最近读过的其他东西

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

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

function b(val) { ... }
于 2012-05-23T01:19:10.517 回答
1

回调是 Javascript 的重要组成部分。Javascript 旨在利用它们。我认为我们永远不会得到某种“同步器”。相反,我们正在获得越来越多的工具来异步执行操作,例如Workers.

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

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

于 2012-05-23T00:28:25.977 回答
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.
于 2012-05-23T01:45:49.340 回答