Q.all为什么这样实现?

时间:2014-11-08 10:56:33

标签: javascript q

我假设Q.all([p1, p2, p3]).then(f)

没什么不同
p1.then(function () {
    p2.then(function () {
        p3.then(f);
    });
});

因为当p1p2p3创建时,异步调用已经完成,我们只需等待所有这些调用解决,订单无关紧要

我说错了吗?

如果是这样,我一直在关注kriskowal's all implementation。我认为它会类似(使用then链接承诺)。但我发现它的实现方式完全不同?那是为什么?

修改

让我更清楚一点。假设p1,p2,p3分别在100ms,200ms,300ms内解析。等待响应的顺序没有区别

p1.then(function () {
    // we're here at 100ms
    p2.then(function () {
        // 100ms later we're here
        p3.then(f); // f gets called 100ms later (at 300ms)
    });
});

p3.then(function () {
    // we're here at 300ms
    p2.then(function () {
        // boom! resolves in a snap
        p1.then(f); // f also gets called instantly (at 300ms)
    });
});

在这两个例子中,我们只等待300毫秒才能解决所有三个承诺。

2 个答案:

答案 0 :(得分:4)

  

我假设Q.all([p1, p2, p3]).then(f)

没什么不同
p1.then(function () {
    p2.then(function () {
        p3.then(f);
    });
});

不完全是。 f传递了一系列结果,你总是希望return(承诺)结果;所以你要写

p1.then(function(r1) {
    return p2.then(function(r1) {
        return p3.then(function(r3) {
            return f([r1, r2, r3]);
        });
    });
});

// or equivalently, better matching a separate `Q.all`:
p1.then(function(r1) {
    return p2.then(function(r1) {
        return p3.then(function(r3) {
            return [r1, r2, r3];
        });
    });
}).then(f);
  

因为当创建p1,p2和p3时,异步调用已经存在   已经完成,我们只需要等待他们所有人解决和   订单并不重要。

     

我说错了吗?

有点儿。实际上,.all的天真版本可以像这样实现。

然而,我们需要看一个重要的边缘"案例:当承诺未能兑现但被拒绝时。突然之间,回调的嵌套结构变得错误 - 因为我们想要从一开始就并行地观察所有三个承诺。我们假设p3在200ms后解析,p1在300ms后解析,p2在100ms后被拒绝。

使用嵌套的then回调,它会在第一次观察p1之前等待整个300毫秒(p2) - 但是,它早已被拒绝了。相反,.all方法希望提前失败,并且只要任何传递的承诺被拒绝,就会拒绝结果承诺。

因此(以及一点性能),Q.all在内部使用deferred pattern

答案 1 :(得分:0)

不。他们是不同的。

在此,假设p2仅在p1完成后才开始。 p3完成后才进行p3。

p1.then(function () {
    p2.then(function () {
        p3.then(f);
    });
});

所以基本上,你引入了序列和依赖。做1,然后是2,然后是3.如果p3取决于p2的结果,p2取决于p1的结果,这是理想的。但是,这会给您的代码带来很多复杂性和依赖性,因此您最好仔细使用它。或者甚至尽可能地避免它。

但是,以下内容不需要序列:

Q.all([p1, p2, p3]).then(f)

f取决于所有3个完成(p1,p2和p3),但三者之间没有交叉依赖。 p2可能先完成,然后是p1或p3(它们是异步的)。无需订单。唯一的要求是所有三个都以f的触发顺序完成。一般来说,这在可能的情况下要好得多。 p2和p3不必等到p1完成后才开始发出请求或处理任何内容。

希望我回答你的问题:)