在javascript中链接异步调用的正确方法是什么? [英] What is the correct way to chain async calls in javascript?

查看:198
本文介绍了在javascript中链接异步调用的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到创建异步调用的最佳方法,因为每次调用都取决于之前的调用已完成。目前我通过递归调用定义的过程函数来链接方法,如下所示。

I'm trying to find the best way to create async calls when each call depends on the prior call to have completed. At the moment I'm chaining the methods by recursively calling a defined process function as illustrated below.

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

This is what I'm currently doing.

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

我会按如下方式将其称为

I would then call this as follows

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

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

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

While this works perfectly fine for me I can't help but think there has to be a better (simpler) way. What happens later when my recursive calls get too deep?

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

NOTE: I am not using javascript in the browser but natively within the Titanium framework, this is akin to Javascript for Node.js.

推荐答案

有很多库和工具可以执行异步链接和控制流程对于你而言,它们主要有两种主要形式:

There are lots of libraries and tools that do async chaining and control-flow for you and they mostly come in two main flavours:


  1. 控制流库

例如,请参阅 async seq 步骤(基于回调)或 Q 期货(基于承诺)。这些的主要优点是它们只是平原JS库,可以减轻异步编程的痛苦。

For example, see async, seq and step (callback based) or Q and futures (promise based). The main advantage of these is that they are just plains JS libraries that ease the pain of async programming.

根据我的个人经验,基于承诺的库往往导致代码看起来更像通常的同步代码,因为你使用return返回值,因为promise值可以传递和存储,类似于实际值。

In my personal experience, promise-based libraries tend to lead to code that looks more like usual synchronous code, since you return values using "return" and since promise values can be passed and stored around, similarly to real values.

另一方面手,基于延续的代码是更低级别,因为它明确地操纵代码路径。这可能允许更灵活的控制流程和更好地与现有库集成,但它也可能导致更多的样板和更不直观的代码。

On the other hand, continuation-based code is more low level since it manipulates code paths explicitely. This can possibly allow for more flexible control flow and better integration with existing libraries, but it might also lead to more boilerplaty and less intuitive code.

Javascript CPS编译器

扩展语言以添加协同程序/生成器的本机支持,可以以非常简单的方式编写异步代码,并与其余部分一起使用语言意味着您可以使用Javascript if语句,循环等而不需要使用函数复制它们。这也意味着它很容易将以前的同步代码转换为异步版本。但是,显而易见的缺点是并非每个浏览器都会运行您的Javascript扩展,因此您需要在构建过程中添加一个编译步骤,以便将您的代码转换为具有continuation-passing-style回调的常规JS。无论如何,一个有希望的替代方案是Ecmascript 6规范中的生成器 - 虽然目前只有firefox支持它们,但是有一些项目,例如再生器 Traceur 将它们编译回回调。还有其他项目创建自己的异步语法(因为es6生成器当时没有出现)。在此类别中,您可以找到 tamejs Iced Coffeescript 。最后,如果您使用Node.js,您还可以查看纤维

Extending the language to add native support for coroutines/generators lets you write asynchronous code in a very straightforward manner and plays nice with the rest of the language meaning you can use Javascript if statements, loops etc instead of needing to replicate them with functions. This also means that its very easy to convert previously sync code into an async version. However, there is the obvious disadvantage that not every browser will run your Javascript extension so you will need to add a compilation step in your build proccess to convert your code to regular JS with callbacks in continuation-passing-style. Anyway, one promising alternative is the generators in the Ecmascript 6 spec - while only firefox supports them natively as of now, there are projects such as regenerator and Traceur to compile them back to callbacks. There are also other projects that create their own async syntax (since es6 generators hadn't come up back then). In this category, you will find things such as tamejs and Iced Coffeescript. Finally, if you use Node.js there you could also take a look at Fibers.






我的推荐:

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

If you just want something simple that won't complicate your build proccess, I would recomend going with whatever control-flow library best fits your personal style and the libraries you already use.

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

However, if you expect to write lots of complicated and deeply-integrated asynchronous code, I would strongly recommend at least looking into a compiler-based alternative.

这篇关于在javascript中链接异步调用的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆