互换的青春
正如您在问题中所暗示的,您的代码同步地创建所有承诺。相反,应该只在前一个解析时创建它们。第二,每一个承诺new Promise需要通过调用resolve(或reject)。这应该在计时器过期时进行。会触发任何then你就可以收回你的承诺了。而这样的then回调(或await)是执行链所必需的。有了这些成分,有几种方法可以执行这个异步链接:带着for循环,以立即解决承诺开始。带着Array#reduce首先是一个立竿见影的承诺具有将自身传递为分辨率回调的函数。与ECMAScript2017async / await句法与提议的ECMAScript 2020for await...of句法请参阅下面每个选项的代码段和注释。1.与for你,你们能,会,可以用for循环,但您必须确保它不执行new Promise同步。相反,您创建一个初始的立即解决承诺,然后链接新的承诺,就像前面的承诺一样:for (let i = 0, p = Promise.resolve(); i < 10; i++) {
p = p.then(_ => new Promise(resolve =>
setTimeout(function () {
console.log(i);
resolve();
}, Math.random() * 1000)
));}2.与reduce这只是对以前策略的一种更有功能的方法。创建一个与要执行的链长度相同的数组,并从立即解析承诺开始[...Array(10)].reduce( (p, _, i) =>
p.then(_ => new Promise(resolve =>
setTimeout(function () {
console.log(i);
resolve();
}, Math.random() * 1000)
)), Promise.resolve() );这可能更有用有在承诺中使用数据的数组。3.函数本身作为分辨率回调。这里我们创建一个函数并立即调用它。它同步地创建了第一个承诺。当它解析时,将再次调用该函数:(function loop(i) {
if (i < 10) new Promise((resolve, reject) => {
setTimeout( () => {
console.log(i);
resolve();
}, Math.random() * 1000);
}).then(loop.bind(null, i+1));})(0);这将创建一个名为loop,在代码的末尾,您可以看到它被立即用参数0调用。这是柜台,i争论。该函数将创建一个新的承诺,如果计数器仍然低于10,否则链接停止。打电话给resolve()将触发then回调,这将再次调用该函数。loop.bind(null, i+1)只是另一种说法_ => loop(i+1).4.与async/await现代JS发动机支持此语法:(async function loop() {
for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, Math.random() * 1000));
console.log(i);
}})();它看起来可能很奇怪,因为它似乎就像new Promise()调用是同步执行的,但实际上async功能回报当它执行第一个await..每次等待的承诺解决后,函数的运行上下文都会被恢复,并在await,直到遇到下一个,直到循环结束。由于基于超时返回承诺可能是一件常见的事情,您可以创建一个单独的函数来生成这样的承诺。这叫做亲化函数,在这种情况下setTimeout..它可以提高代码的可读性:const delay = ms => new Promise(resolve => setTimeout(resolve, ms));(async function loop() {
for (let i = 0; i < 10; i++) {
await delay(Math.random() * 1000);
console.log(i);
}})();5.与for await...of甚至最近for await...of语法出现在一些JavaScript引擎上。虽然在这种情况下它并没有真正减少代码,但它允许将随机区间链的定义与实际的迭代隔离开来:const delay = ms => new Promise(resolve => setTimeout(resolve, ms));async function * randomDelays(count ,max) {
for (let i = 0; i < count; i++) yield delay(Math.random() * max).then(() => i);}(async function loop() {
for await (let i of randomDelays(10, 1000)) console.log(i);})();