我有一个函数F,它启动一个异步进程X.该函数返回一个在X结束时解析的promise(我通过X返回的promise来学习) .
当(w.l.o.g.)X,X1的第一个实例正在运行时,可能会有更多对F的调用 . 每个调用都会产生一个新的X实例,例如: X2,X3等 .
Now, here's the difficulty: 创建X2时,根据X1的状态,X1应该结束或中止 . 只有X1不再处于活动状态时,X2才会开始工作 . In any case, the unresolved promises returned from all previous calls to F should be resolved only once X2 has concluded, as well - or, any later instance of X, if F gets called again while X2 is running.
到目前为止,对F的第一次调用调用 $q.defer()
来创建一个延迟,其承诺由对F的所有调用返回,直到最后一个X结束 . (然后,应该解析延迟,并且保存它的字段应该重置为null,等待下一个对F的调用集群 . )
现在,我的问题是等到X的所有实例都完成了 . 我知道如果事先有完整的X实例列表,我可以使用 $q.all
但是因为我必须考虑以后调用F,所以这不是解决方案 . 理想情况下,我可能应该将一些事情转换为X返回的承诺以解决延迟的问题,并且只要我将其链接到X的后续实例,就可以使用"unchain"该功能 .
我想像这样的事情:
var currentDeferred = null;
function F() {
if (!currentDeferred) {
currentDeferred = $q.defer();
}
// if previous X then "unchain" its promise handler
X().then(function () {
var curDef = currentDeferred;
currentDeferred = null;
curDef.resolve();
});
return currentDeferred.promise;
}
但是,如果这是一个正确的解决方案,我不知道如何执行“不加协调” .
How do I go about this? Am I missing some common pattern or even built-in feature of promises, or am I on the wrong track altogether?
添加一些上下文:调用F来加载数据(异步)并更新一些可视输出 . F返回一个只有在视觉输出再次更新到稳定状态(即没有更多待更新)时才能解析的promise .
1 回答
由于
F
的所有呼叫者都将收到他们需要消费的承诺,但您只想在所有堆叠呼叫完成后更新UI,最简单的方法是让每个承诺解决(或拒绝)一个值,告诉呼叫者不要如果有另一个"get more data"呼叫待处理,则更新UI;这样,只有其承诺最后解析的调用者才会更新UI . 你可以通过跟踪未完成的电话来做到这一点:(这是本机承诺;根据
$q
的需要进行调整 . )对我来说,"don't update"与"failed,"不同,所以我使用了一个标志值(
null
),而不是拒绝信号 . 但是当然,你也可以使用带有标志值的拒绝,它在catch
处理程序中更新“?”而不是你的then
[这是真实的数据吗?] ......嗯,我可能会走另一条路现在我想到了 . 但那是微不足道的改变 . )显然,上面的
accumulator
只是您真实数据结构的原始占位符(并且它不会尝试按照请求的顺序保持接收的数据) .我有承诺解决上面的数据副本(
accumulator.slice()
),但在您的情况下可能没有必要 .