我正在努力建立带有SettieTimeout的Promise Chain。所有的承诺都需要以串联而不平行的方式运行。我正在使用蓝鸟模块实现承诺执行的串行流。
有人可以向我解释为什么此代码为我提供1,2,3,4而不是4,3,2,1?
的输出
var bluebirdPromise = require('bluebird');
function p1(value) {
return new Promise(function(resolve, reject) {
setTimeout(function(resolve) {
console.log(value);
resolve;
}, value * 1000);
});
}
var arr = [p1(4), p1(3), p1(2), p1(1)];
bluebirdPromise.reduce(arr,
function(item, index, length) {
}).then(function (result) {
});
有几个问题:
-
您所拥有的
<</p> <。console.log
并非取决于先前的解决承诺。只有超时确定 将发生输出。当您在"同一"时间创建所有四个诺言时,同时调用了所有四个setTimeout
调用,他们的回调将在确定的超时时访问。链条之后您的链条承诺无关紧要...要解决此问题,您需要在then
回调中移动console.log
,因为该回调只有在解决链条中的先前承诺时才能执行。 -
在您的代码中未调用
resolve
功能。您需要添加括号。 -
setTimeout
回调的分辨率参数隐藏了 real> real 函数,具有相同名称:您需要删除该参数。
这是建议的校正。对于此片段,我已经用标准Array#reduce
替换了蓝鸟reduce
,但它可以与Bluebird的reduce
相似。
function p1(value) {
return new Promise(function(resolve, reject) {
setTimeout(function() { // ***
resolve(value); // ***
}, value * 1000);
});
}
var arr = [p1(4), p1(3), p1(2), p1(1)];
arr.reduce(function(promise, next) {
return promise.then(_ => next).then( value => {
console.log(value); // ***
return value;
});
}, Promise.resolve());
如果您具有Promist-Creator函数p
,并且您想在serial 中运行一系列Promises ,则无需您加载一个数组有了承诺 - 而是让它成为正常的值
请注意,我也不在这里使用value * 1000
- 在您的代码中,您认为您必须使用计算的Settimeout延迟来人为地编排以特定顺序发射的承诺;事实并非如此。仔细观察以下代码的评估,以了解我们如何在每个诺言和.then
之间有1秒的延迟使事情保持顺序
还要注意,该代码将在第一个承诺解决之后立即开始输出 - 而不是等待所有承诺在输出所有值之前解决的所有承诺
const p = x =>
new Promise(f =>
setTimeout(f, 1e3, x))
const arr = [4,3,2,1]
arr.reduce((acc, x) =>
acc.then(() => p(x)).then(console.log), Promise.resolve())
好,所以您有这些承诺按顺序运行,但是为什么呢?除非以后的步骤以某种方式取决于早期步骤的结果,否则您没有理由要减慢这些速度 - 即,每个诺言的结果不依赖其他结果,因此只需尽可能快地计算它们即可。但是您担心订单会丢失,对吗?不用担心,一切都会好起来的 - 我什至会使用随机延迟向您展示每个诺言都不重要的时间
const p = x =>
new Promise(f =>
setTimeout(f, 1e3 * Math.random(), x))
const arr = [4,3,2,1]
arr.map(p).reduce((acc, x) =>
acc.then(() => x).then(console.log), Promise.resolve())
现在,现在所有的承诺都可以立即开始,一旦解决了第一个承诺,输出将立即开始(与Promise不同。所有承诺都等待所有承诺在您可用的任何值之前完成的所有承诺(。
我仅作为替代方案而提到这一点,因为您提供的示例不显示真正的需要 serial执行的承诺。您可能已经天真地简化了问题的域名,但只有您是否知道情况。