JavaScript 使用 setTimeout 的串行承诺
JavaScript Serial Promises with setTimeout
我正在努力构建其中包含 setTimeouts 的 Promise 链。所有的 Promise 都需要 运行 串联而不是并行。我正在使用 Bluebird 模块来实现 Promise 执行的串行流程。
有人能解释一下为什么这段代码输出的是 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) {
});
有几个问题:
您拥有的 console.log
不依赖于先前已解决的承诺。只有超时决定了什么时候输出会发生。当您在 "same" 时间创建所有四个承诺,因此所有四个 setTimeout
调用被同时调用,它们的回调 将 在确定的超时时间被调用.之后如何链接承诺并不重要......要解决这个问题,您需要在 then
回调中移动 console.log
,因为该回调只会在链中的前一个承诺具有时执行已解决。
您的代码中未调用 resolve
函数。您需要添加括号。
setTimeout
回调的 resolve 参数隐藏了 real 同名函数:您需要删除该参数。
这是建议的更正。对于此代码段,我已将蓝鸟 reduce
替换为标准 Array#reduce
,但它与蓝鸟的 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());
如果您有一个 promise-creator 函数,p
,并且您想要运行一系列 promise 串行,则不需要你加载一个带有承诺的数组——相反,让它成为一个普通的值数组
请注意,我在这里也没有使用 value * 1000
– 在您的代码中,您认为您必须使用计算的 setTimeout 延迟人为编排承诺以特定顺序触发;事实并非如此。仔细观察下面代码的评估,看看我们如何在每个承诺之间有 1 秒的延迟,.then
使事情井井有条
另请注意,此代码将在第一个承诺解决后立即开始输出——而不是在输出所有值之前等待所有承诺解决
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())
好的,所以你有这些承诺 运行ning 按顺序排列,但为什么呢?除非后面的步骤以某种方式依赖于前面步骤的结果,否则您没有理由要放慢这些速度——即,每个承诺的结果不依赖于其他步骤,所以尽可能快地计算它们。但是你担心订单会丢失,对吧?别担心,一切都会好起来的——我什至会用一个随机延迟来告诉你每个承诺所花的时间并不重要
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.all 会等待所有承诺完成,然后您才能使用任何值).
我只是将此作为替代方案提及,因为您提供的示例显示没有真正需要 连续执行承诺。您可能天真地简化了问题的域,但事实是否如此只有您自己知道。
我正在努力构建其中包含 setTimeouts 的 Promise 链。所有的 Promise 都需要 运行 串联而不是并行。我正在使用 Bluebird 模块来实现 Promise 执行的串行流程。
有人能解释一下为什么这段代码输出的是 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) {
});
有几个问题:
您拥有的
console.log
不依赖于先前已解决的承诺。只有超时决定了什么时候输出会发生。当您在 "same" 时间创建所有四个承诺,因此所有四个setTimeout
调用被同时调用,它们的回调 将 在确定的超时时间被调用.之后如何链接承诺并不重要......要解决这个问题,您需要在then
回调中移动console.log
,因为该回调只会在链中的前一个承诺具有时执行已解决。您的代码中未调用
resolve
函数。您需要添加括号。setTimeout
回调的 resolve 参数隐藏了 real 同名函数:您需要删除该参数。
这是建议的更正。对于此代码段,我已将蓝鸟 reduce
替换为标准 Array#reduce
,但它与蓝鸟的 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());
如果您有一个 promise-creator 函数,p
,并且您想要运行一系列 promise 串行,则不需要你加载一个带有承诺的数组——相反,让它成为一个普通的值数组
请注意,我在这里也没有使用 value * 1000
– 在您的代码中,您认为您必须使用计算的 setTimeout 延迟人为编排承诺以特定顺序触发;事实并非如此。仔细观察下面代码的评估,看看我们如何在每个承诺之间有 1 秒的延迟,.then
使事情井井有条
另请注意,此代码将在第一个承诺解决后立即开始输出——而不是在输出所有值之前等待所有承诺解决
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())
好的,所以你有这些承诺 运行ning 按顺序排列,但为什么呢?除非后面的步骤以某种方式依赖于前面步骤的结果,否则您没有理由要放慢这些速度——即,每个承诺的结果不依赖于其他步骤,所以尽可能快地计算它们。但是你担心订单会丢失,对吧?别担心,一切都会好起来的——我什至会用一个随机延迟来告诉你每个承诺所花的时间并不重要
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.all 会等待所有承诺完成,然后您才能使用任何值).
我只是将此作为替代方案提及,因为您提供的示例显示没有真正需要 连续执行承诺。您可能天真地简化了问题的域,但事实是否如此只有您自己知道。