javascript - 在javascript中链接异步调用的正确方法是什么?

标签 javascript node.js titanium titanium-mobile serverside-javascript

当每个调用都依赖于之前的调用完成时,我正在尝试找到创建异步调用的最佳方法。目前,我通过递归调用定义的流程函数来链接方法,如下所示。

这就是我目前正在做的事情。

var syncProduct = (function() {
    var done, log;
    var IN_CAT = 1, IN_TITLES = 2, IN_BINS = 3;
    var state = IN_CAT;
    var processNext = function(data) {
        switch(state) {
            case IN_CAT:
                SVC.sendJsonRequest(url("/api/lineplan/categories"), processNext);
                state = IN_TITLES;
                break;
            case IN_TITLES:
                log((data ? data.length : "No") + " categories retrieved!");
                SVC.sendJsonRequest(url("/api/lineplan/titles"), processNext);
                state = IN_BINS;
                break;
            case IN_BINS:
                log((data ? data.length : "No") + " titles retrieved!");
                SVC.sendJsonRequest(url("/api/lineplan/bins"), processNext);
                state = IN_MAJOR;
                break;
            default:
                log((data ? data.length : "No") + " bins retrieved!");
                done();
                break;
        }
    }
    return {
        start: function(doneCB, logCB) {
            done = doneCB; log = logCB; state = IN_CAT;
            processNext();
        }
    }
})();

然后我会这样调用它

var log = function(message) {
    // Impl removed.
}

syncProduct.start(function() {
    log("Product Sync Complete!");
}, log);

虽然这对我来说非常有效,但我不禁认为必须有更好(更简单)的方法。当我的递归调用太深时会发生什么?

注意:我没有在浏览器中使用 javascript,而是在 Titanium 框架中使用 native ,这类似于 Node.js 的 Javascript。

最佳答案

有很多库和工具可以为您执行异步链接和控制流,它们主要有两种主要风格:

  1. 控制流库

    例如,参见 async , seqstep (基于回调)或Qfutures (基于 promise )。这些的主要优点是它们只是简单的 JS 库,可以减轻异步编程的痛苦。

    根据我的个人经验,基于 Promise 的库往往会导致代码看起来更像通常的同步代码,因为您使用“return”返回值,并且 Promise 值可以传递和存储,类似于真实值。

    另一方面,基于延续的代码更底层,因为它显式地操作代码路径。这可能允许更灵活的控制流并更好地与现有库集成,但也可能导致更多的样板和不直观的代码。

  2. Javascript CPS 编译器

    扩展语言以添加对协同程序/生成器的 native 支持,让您以非常简单的方式编写异步代码,并且与语言的其余部分配合得很好,这意味着您可以使用 Javascript if 语句、循环等,而无需复制它们功能。这也意味着将以前的同步代码转换为异步版本非常容易。但是,有一个明显的缺点是并非每个浏览器都会运行您的 Javascript 扩展,因此您需要在构建过程中添加一个编译步骤,以将您的代码转换为具有持续传递样式回调的常规 JS。无论如何,一个有希望的替代方案是 Ecmascript 6 规范中的生成器 - 虽然到目前为止只有 Firefox 原生支持它们,但有一些项目,例如 regeneratorTraceur将它们编译回回调。还有其他项目创建了自己的异步语法(因为当时 es6 生成器还没有出现)。在此类别中,您会找到诸如 tamejs 之类的内容。和 Iced Coffeescript .最后,如果您在那里使用 Node.js,您还可以查看 Fibers .


我的建议:

如果您只是想要一些不会使您的构建过程复杂化的简单的东西,我建议您使用最适合您的个人风格和您已经使用的库的任何控制流库。

但是,如果您希望编写大量复杂且深度集成的异步代码,我强烈建议您至少研究基于编译器的替代方案。

关于javascript - 在javascript中链接异步调用的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9432587/

相关文章:

titanium - 加速器 : I'm failing at 403 during build

android - 图像在android中自动旋转

javascript - 如何使用 Browserify 指定自定义搜索路径?

javascript - 根据类名更改 vue.js 中的背景颜色

javascript - 折叠的导航栏不起作用 react 和引导 5

node.js - 使用 Nodejs Sequelize 避免竞争条件

javascript - 将 xml 转换为 json

javascript - 如何从 Webhook 运行 Gulp

macos - Titanium 开发人员在启动时崩溃(很好)

Javascript 将数据插入 HTML 表格