亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JavaScript ES6承諾循環

JavaScript ES6承諾循環

守候你守候我 2019-07-16 16:50:34
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().你怎么解決這個問題?
查看完整描述

3 回答

?
慕田峪9158850

TA貢獻1794條經驗 獲得超8個贊

正如您在問題中所暗示的,您的代碼同步地創建所有承諾。相反,應該只在前一個解析時創建它們。

第二,每一個承諾new Promise需要通過調用resolve(或reject)。這應該在計時器過期時進行。會觸發任何then你就可以收回你的承諾了。而這樣的then回調(或await)是執行鏈所必需的。

有了這些成分,有幾種方法可以執行這個異步鏈接:

  1. 帶著for循環,以立即解決承諾開始。

  2. 帶著Array#reduce首先是一個立竿見影的承諾

  3. 具有將自身傳遞為分辨率回調的函數。

  4. 與ECMAScript2017async / await句法

  5. 與提議的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);})();



查看完整回答
反對 回復 2019-07-16
  • 3 回答
  • 0 關注
  • 519 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號