作为一个简化的案例,我有两个异步函数,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.
});
第一种方法更优雅,第二种方法更有效.