您已按“方式 1”对计时器进行排序(它们每一个触发一秒钟)并以“方式 2”并行运行您的计时器,因此所有计时器几乎同时触发。下面是更详细的解释:
在“方式 1”中,您使用 sequence = sequence.then() 创建一个承诺链,并从序列中调用 setTimeout()。因此,计时器 2 直到计时器 1 触发后才会启动,依此类推。您将让每个单独的计时器真正按顺序运行,每次触发大约相隔 1 秒。
在“方式 2”中,您在 .map() 中一次启动所有计时器,因此所有计时器并行运行,而不是按顺序运行。然后你试图用你的sequence2 = sequence2.then() 循环强制它们进入一个序列,但是异步操作已经并行启动了,所以所有这个顺序循环实际上并没有比Promise.all() 在时间方面完成更多的事情。
如果您运行这两个 sn-ps 中的每一个,它们将准确记录计时器何时触发,您可以看到两者之间的区别。
在这里,在记录每个计时器时间序列的“方式 1”版本中,您可以看到计时器间隔大约 1 秒触发:
// way 1
let startTime = Date.now();
function log() {
let args = Array.from(arguments);
// calc time since startTime
let delta = (Date.now() - startTime) / 1000;
args.unshift(delta + ": ");
console.log.apply(console, args);
}
function delay(t, val) {
return new Promise(resolve => {
setTimeout(() => {
log("timer fire");
resolve(val);
}, t);
});
}
// Way 1
let sequence = Promise.resolve();
[1,2,3,4].forEach((val)=> {
sequence = sequence.then(()=> {
return delay(1000, val);
}).then(console.log);
});
sequence.then(() => {
log("all done");
})
在这里,在记录每个计时器时间序列的“方式 2”版本中,您可以看到计时器几乎同时触发:
// way 2
let startTime = Date.now();
function log() {
let args = Array.from(arguments);
// calc time since startTime
let delta = (Date.now() - startTime) / 1000;
args.unshift(delta + ": ");
console.log.apply(console, args);
}
function delay(t, val) {
return new Promise(resolve => {
setTimeout(() => {
log("timer fire");
resolve(val);
}, t);
});
}
//Way 2
let sequence2 = Promise.resolve();
[5,6,7,8].map(val => {
return new delay(1000, val);
}).forEach(promise => {
sequence2 = sequence2.then(() => promise).then(console.log);
});
sequence2.then(() => {
log("all done");
});
在运行每个 sn-p 时,并不是特别是获得“全部完成”消息所需的时间。第一个序列化四个一秒定时器,所以它需要
运行约 4 秒。第二个并行运行所有计时器,因此运行大约需要 1 秒。
补充说明:
当你这样做时:
let arrayOfPromoises = [5,6,7,8].map(val => {
return new Promise(resolve => setTimeout(resolve, 1000, val));
});
该代码连续执行四次return new Promise(resolve => setTimeout(resolve, 1000, val));,一个接一个,没有延迟。由于每次执行该代码时,它都会创建一个新的 Promise 对象,因此您最终会得到一个包含四个 Promise 的数组。
现在,在该代码中,您有以下内容:
new Promise(resolve => setTimeout(resolve, 1000, val));
立即调用 Promise 执行器函数(即您传递给 Promise 构造函数的回调函数)。没有等待。因此,您不仅创建了四个 Promise,而且还启动了四个同时运行的 Promise。这些计时器已经启动。 sequence2 = sequence2.then() 循环的任何结构都不会改变这一点。计时器已在运行。