JavaScript ES6承诺循环

JavaScript ES6承诺循环

for (let i = 0; i < 10; i++) {
    const promise = new Promise((resolve, reject) => {
        const timeout = Math.random() * 1000;
        setTimeout(() => {
            console.log(i);
        }, timeout);
    });

    // TODO: Chain this promise to the previous one (maybe without having it running?)}

以上将提供以下随机输出:

6
9
4
8
5
1
7
2
3
0

任务很简单:确保每个承诺只在另一个承诺之后运行(.then()).

因为某种原因,我找不到办法去做这件事。

我试过发电机功能(yield),尝试了返回承诺的简单函数,但在一天结束时,它总是归结为相同的问题:循环是同步的。.

带着异步我只想用async.series().

你怎么解决这个问题?


守候你守候我
浏览 485回答 3
3回答

慕田峪9158850

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

相关分类

JavaScript