链接超时导致上次超时被拒绝?

Chaining timeouts results in last timeout rejected?

我目前正在尝试将一些承诺与超时联系起来,无论达到哪个超时,它总是报告最后一个。我用 bluebird 和 Q 试过,结果一样,所以我想我有一个普遍的问题。

代码基本上是这样的:

var Promise = require('bluebird');

Promise.delay(2000)
  .then(function() {
    return Promise.delay(2000);
  })
  .timeout(1000, 'Timeout 1')
  .then(function() {
    return Promise.delay(500);
  })
  .timeout(1000, 'Timeout 2')
  .then(function() {
    return Promise.delay(500);
  })
  .timeout(1000, 'Timeout 3');

我正在 "Unhandled rejection TimeoutError: Timeout 3"。我想要的是获得超时 1。我尝试在每次超时后进行捕获,但我得到的都是一样的。

有没有办法让它在不完全拆分的情况下工作?

Bluebird 不保证定时器的执行顺序。因此,如果您将三个超时设置为相同的时间跨度,我们不会强制执行哪一个。如您所见,如果您 运行 浏览器中的此代码 "Timeout 1" 将记录并且不会超时 3:

var p = Promise.delay(2000)
  .then(function() {
    return Promise.delay(2000);
  })
  .timeout(1000, 'Timeout 1')
  .then(function() {
    return Promise.delay(500);
  })
  .timeout(1000, 'Timeout 2')
  .then(function() {
    return Promise.delay(500);
  })
  .timeout(1000, 'Timeout 3');

p.reflect().then(function(res){
  document.body.innerHTML = JSON.stringify(res.reason().message);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.6/bluebird.js"></script>

从技术上讲,bluebird 正在履行其合同。在假设没有异常的指定时间后,如果承诺尚未解决,则将被拒绝。无论此处触发哪个计时器,都是如此。 这只是定时器的排序 - 您应该给它们不同的超时值。

当然,如果你在第一个 .timeout 之后的第一个超时后添加一个 .catch(function(){}) (最好是键入的而不是一般的)你会得到不同的结果。

delaytimeout 使用环境的 setTimeout 函数,在 node.js 中绝对不能保证计时器 运行 的顺序。您基本上需要假设 setTimeout(..., 10) 可能 运行 在 setTimeout(..., 10000) 之后,因此使您的代码依赖于较早的计时器到 运行 在较晚的计时器被破坏后。

目前你有 3 个超时,都要求一切(你的整个链)在 1 秒内完成。
我有一种感觉,你实际上想为每个连续的任务设置 3 个超时:

Promise.delay(2000)
.then(function() {
    return Promise.delay(2000)
    .timeout(1000, 'Timeout 1');
})
.then(function() {
    return Promise.delay(500)
    .timeout(1000, 'Timeout 2');
})
.then(function() {
    return Promise.delay(500)
    .timeout(1000, 'Timeout 3');
});

这将在超时 1 3 秒后被拒绝。