gpt4 book ai didi

javascript - 运行序列 promise 之间的区别是创建一个新的 promise 然后运行和创建所有 promise 然后运行每个 promise

转载 作者:行者123 更新时间:2023-12-03 03:31:28 30 4
gpt4 key购买 nike

请帮我解释一下为什么日志结果有两种不同:

方式 1:每 1 秒顺序记录一次

方式 2:1 秒后记录所有元素。

// Way 1
let sequence = Promise.resolve();
[1,2,3,4].forEach((val)=> {
sequence = sequence.then(()=> {
return new Promise(resolve => setTimeout(resolve, 1000, val))
}).then(console.log);
})


//Way 2
let sequence2 = Promise.resolve();
[5,6,7,8].map(val => {
return new Promise(resolve => setTimeout(resolve, 1000, val));
}).forEach(promise => {
sequence2 = sequence2.then(() => promise).then(console.log);
});

已编辑:以方式 2 描述错误的日志结果

最佳答案

您已按“方式 1”对计时器进行排序(每个计时器间隔一秒触发),并按“方式 2”并行运行计时器,因此计时器几乎同时触发。更详细的解释如下:

在“方式 1”中,您使用 sequence =equence.then() 创建一个 Promise 链,并从序列中调用 setTimeout()。因此,定时器 2 直到定时器 1 触发后才会启动,依此类推。您将使每个单独的计时器真正按顺序运行,每次触发间隔约 1 秒。

在“方式 2”中,您在 .map() 中同时启动所有计时器,因此所有计时器都是并行运行的,而不是按顺序运行。然后,您尝试使用 sequence2 =equence2.then() 循环强制它们进入序列,但异步操作已经并行启动,因此所有这些顺序循环实际上并没有完成任何事情Promise.all() 会在时间方面。

如果您运行这两个代码片段,它们将在计时器触发时准确记录,您可以看到两者之间的差异。

在这里,在记录每个计时器的时间顺序的“方式 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");
});

运行每个片段时,不要特别关注到达“全部完成”消息所需的时间。第一个序列化了四个一秒计时器,因此需要运行约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,而且还启动了四次同时运行的操作。这些计时器已经启动。使用 sequence2 =equence2.then() 循环构建任何结构都不会改变这一点。计时器已在运行。

关于javascript - 运行序列 promise 之间的区别是创建一个新的 promise 然后运行和创建所有 promise 然后运行每个 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46078271/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com