如何实现JavaScript中异步函数之间的依赖关系?

作为一个简化的案例,我有两个异步函数,foo和bar. bar需要foo的结果,即bar取决于foo.我不知道将首先调用哪个函数.

>如果先调用bar,bar将调用foo并在foo完成后立即启动.
>如果首先调用foo并完成,则bar可以使用foo的结果.
>如果首先调用foo并在foo完成之前调用bar,则bar需要等待foo的结果. (不要调用对foo的新调用,只需等待已经触发的foo调用)

我怎样才能做到这一点?
是否可以注册异步函数依赖链(类似于require.js中的依赖项define [‘foo’],function(){bar();})?
我可以使用$.deferred()来实现它吗?
怎么样?

最佳答案 在这种情况下,标准方法是缓存较低级别的承诺.

通常,您将在某些合适的外部作用域中将js plain对象建立为promise缓存,并在调用异步进程之前始终先查看该对象.

var promiseCache = {};

function foo() {
    if(!promiseCache.foo) {
        promiseCache.foo = doSomethingAsync();
    }
    return promiseCache.foo;
}

function bar() {
    return foo().then(doSomethingElseAsync);
}

当然,如果合适的话,没有什么可以阻止你缓存更高级别的承诺.

function bar() {
    if(!promiseCache.bar) {
        promiseCache.bar = foo().then(doSomethingElseAsync);
    }
    return promiseCache.bar;
}

编辑:forceRefresh功能

您可以通过传递(额外)参数来强制函数刷新其缓存的promise.

function foo(any, number, of, other, arguments, forceRefresh) {
    if(forceRefresh || !promiseCache.foo) {
        promiseCache.foo = doSomethingAsync();
    }
    return promiseCache.foo;
}

通过使forceRefresh成为最后一个参数,将其保留为与传递false相同,如果可用,foo将使用缓存的promise.或者,传递true以保证调用doSomethingAsync()并刷新缓存的值.

编辑2:setName()/ getName()

在getName()中使用forceRefresh机制:

setName(newName).then(getName.bind(null, true)); //set new name then read it back using forceRefresh.

或者,省略forceRefresh机制,并假设cache属性为promiseCache.name:

setName(newName).then(function() {
    promiseCache.name = $.when(newName);//update the cache with a simulated `getName()` promise.
});

第一种方法更优雅,第二种方法更有效.

点赞