溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript循環中怎么使用 async/await

發布時間:2020-12-01 10:27:08 來源:億速云 閱讀:347 作者:小新 欄目:web開發

小編給大家分享一下JavaScript循環中怎么使用 async/await,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

asyncawait 的使用方式相對簡單。 但當你嘗試在循環中使用await時,事情就會變得復雜一些。

在本文中,分享一些在如果循環中使用await值得注意的問題。

準備一個例子

對于這篇文章,假設你想從水果籃中獲取水果的數量。

const fruitBasket = {
 apple: 27,
 grape: 0,
 pear: 14
};

你想從fruitBasket獲得每個水果的數量。 要獲取水果的數量,可以使用getNumFruit函數。

const getNumFruit = fruit => {
  return fruitBasket[fruit];
};

const numApples = getNumFruit('apple');
console.log(numApples); //27

現在,假設fruitBasket是從服務器上獲取,這里我們使用 setTimeout 來模擬。

const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms))
};

const getNumFruie = fruit => {
  return sleep(1000).then(v => fruitBasket[fruit]);
};

getNumFruit("apple").then(num => console.log(num)); // 27

最后,假設你想使用awaitgetNumFruit來獲取異步函數中每個水果的數量。

const control = async _ => {
  console.log('Start')

  const numApples = await getNumFruit('apple');
  console.log(numApples);

  const numGrapes = await getNumFruit('grape');
  console.log(numGrapes);

  const numPears = await getNumFruit('pear');
  console.log(numPears);

  console.log('End')
}

JavaScript循環中怎么使用 async/await

在 for 循環中使用 await

首先定義一個存放水果的數組:

const fruitsToGet = [“apple”, “grape”, “pear”];

循環遍歷這個數組:

const forLoop = async _ => {
  console.log('Start');
  
  for (let index = 0; index < fruitsToGet.length; index++) {
    // 得到每個水果的數量
  }

  console.log('End')
}

for循環中,過上使用getNumFruit來獲取每個水果的數量,并將數量打印到控制臺。

由于getNumFruit返回一個promise,我們使用 await 來等待結果的返回并打印它。

const forLoop = async _ => {
  console.log('start');

  for (let index = 0; index < fruitsToGet.length; index ++) {
    const fruit = fruitsToGet[index];
    const numFruit = await getNumFruit(fruit);
    console.log(numFruit);
  }
  console.log('End')
}

當使用await時,希望JavaScript暫停執行,直到等待 promise 返回處理結果。這意味著for循環中的await 應該按順序執行。

結果正如你所預料的那樣。

“Start”;
“Apple: 27”;
“Grape: 0”;
“Pear: 14”;
“End”;

JavaScript循環中怎么使用 async/await

這種行為適用于大多數循環(比如whilefor-of循環)…

但是它不能處理需要回調的循環,如forEach、map、filterreduce。在接下來的幾節中,我們將研究await 如何影響forEach、map和filter。

在 forEach 循環中使用 await

首先,使用 forEach 對數組進行遍歷。

const forEach = _ => {
  console.log('start');

  fruitsToGet.forEach(fruit => {
    //...
  })

  console.log('End')
}

接下來,我們將嘗試使用getNumFruit獲取水果數量。 (注意回調函數中的async關鍵字。我們需要這個async關鍵字,因為await在回調函數中)。

const forEachLoop = _ => {
  console.log('Start');

  fruitsToGet.forEach(async fruit => {
    const numFruit = await getNumFruit(fruit);
    console.log(numFruit)
  });

  console.log('End')
}

我期望控制臺打印以下內容:

“Start”;
“27”;
“0”;
“14”;
“End”;

但實際結果是不同的。在forEach循環中等待返回結果之前,JavaScrip先執行了 console.log('End')。

實際控制臺打印如下:

‘Start’
‘End’
‘27’
‘0’
‘14’

JavaScript循環中怎么使用 async/await

JavaScript 中的 forEach不支持 promise 感知,也支持 asyncawait,所以不能在 forEach 使用 await 。

在 map 中使用 await

如果在map中使用await, map 始終返回promise數組,這是因為異步函數總是返回promise。

const mapLoop = async _ => {
  console.log('Start')
  const numFruits = await fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit;
  })
  
  console.log(numFruits);

  console.log('End')
}
      

“Start”;
“[Promise, Promise, Promise]”;
“End”;

JavaScript循環中怎么使用 async/await

如果你在 map 中使用 await,map 總是返回promises,你必須等待promises 數組得到處理。 或者通過await Promise.all(arrayOfPromises)來完成此操作。

const mapLoop = async _ => {
  console.log('Start');

  const promises = fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit;
  });

  const numFruits = await Promise.all(promises);
  console.log(numFruits);

  console.log('End')
}

運行結果如下:

JavaScript循環中怎么使用 async/await

如果你愿意,可以在promise 中處理返回值,解析后的將是返回的值。

const mapLoop = _ => {
  // ...
  const promises = fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit + 100
  })
  // ...
}
 
“Start”;
“[127, 100, 114]”;
“End”;

在 filter 循環中使用 await

當你使用filter時,希望篩選具有特定結果的數組。假設過濾數量大于20的數組。

如果你正常使用filter (沒有 await),如下:

const filterLoop =  _ => {
  console.log('Start')

  const moreThan20 =  fruitsToGet.filter(async fruit => {
    const numFruit = await fruitBasket[fruit]
    return numFruit > 20
  })
  
  console.log(moreThan20) 
  console.log('END')
}

運行結果

Start
["apple"]
END

filter 中的await不會以相同的方式工作。 事實上,它根本不起作用。

const filterLoop = async _ => {
  console.log('Start')

  const moreThan20 =  await fruitsToGet.filter(async fruit => {
    const numFruit = fruitBasket[fruit]
    return numFruit > 20
  })
  
  console.log(moreThan20) 
  console.log('END')
}


// 打印結果
Start
["apple", "grape", "pear"]
END

JavaScript循環中怎么使用 async/await

為什么會發生這種情況?

當在filter 回調中使用await時,回調總是一個promise。由于promise 總是真的,數組中的所有項都通過filter 。在filter 使用 await類以下這段代碼

const filtered = array.filter(true);

filter使用 await 正確的三個步驟

  1. 使用map返回一個promise 數組

  2. 使用 await 等待處理結果

  3. 使用 filter 對返回的結果進行處理

const filterLoop = async _ => {
  console.log('Start');

  const promises = await fruitsToGet.map(fruit => getNumFruit(fruit));
 
  const numFruits = await Promise.all(promises);

  const moreThan20 = fruitsToGet.filter((fruit, index) => {
    const numFruit = numFruits[index];
    return numFruit > 20;
  })

  console.log(moreThan20);
  console.log('End')
}

JavaScript循環中怎么使用 async/await

在 reduce 循環中使用 await

如果想要計算 fruitBastet中的水果總數。 通常,你可以使用reduce循環遍歷數組并將數字相加。

const reduceLoop = _ => {
  console.log('Start');

  const sum = fruitsToGet.reduce((sum, fruit) => {
    const numFruit = fruitBasket[fruit];
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log('End')
}

運行結果:

JavaScript循環中怎么使用 async/await

當你在 reduce 中使用await時,結果會變得非?;靵y。

 const reduceLoop = async _ => {
  console.log('Start');

  const sum = await fruitsToGet.reduce(async (sum, fruit) => {
    const numFruit = await fruitBasket[fruit];
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log('End')
}

JavaScript循環中怎么使用 async/await

[object Promise]14 是什么 鬼??

剖析這一點很有趣。

  1. 在第一次遍歷中,sum0。numFruit27(通過getNumFruit(apple)的得到的值),0 + 27 = 27。

  2. 在第二次遍歷中,sum是一個promise。 (為什么?因為異步函數總是返回promises?。?code>numFruit是0.promise 無法正常添加到對象,因此JavaScript將其轉換為[object Promise]字符串。 [object Promise] + 0object Promise] 0。

  3. 在第三次遍歷中,sum 也是一個promise。 numFruit14. [object Promise] + 14[object Promise] 14。

解開謎團!

這意味著,你可以在reduce回調中使用await,但是你必須記住先等待累加器!

const reduceLoop = async _ => {
  console.log('Start');

  const sum = await fruitsToGet.reduce(async (promisedSum, fruit) => {
    const sum = await promisedSum;
    const numFruit = await fruitBasket[fruit];
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log('End')
}

JavaScript循環中怎么使用 async/await

但是從上圖中看到的那樣,await 操作都需要很長時間。 發生這種情況是因為reduceLoop需要等待每次遍歷完成promisedSum。

有一種方法可以加速reduce循環,如果你在等待promisedSum之前先等待getNumFruits(),那么reduceLoop只需要一秒鐘即可完成:

const reduceLoop = async _ => {
  console.log('Start');

  const sum = await fruitsToGet.reduce(async (promisedSum, fruit) => {
    const numFruit = await fruitBasket[fruit];
    const sum = await promisedSum;
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log('End')
}

JavaScript循環中怎么使用 async/await

這是因為reduce可以在等待循環的下一個迭代之前觸發所有三個getNumFruit promise。然而,這個方法有點令人困惑,因為你必須注意等待的順序。

在reduce中使用wait最簡單(也是最有效)的方法是

  1. 使用map返回一個promise 數組

  2. 使用 await 等待處理結果

  3. 使用 reduce 對返回的結果進行處理

    const reduceLoop = async _ => {
     console.log('Start');

    const promises = fruitsToGet.map(getNumFruit);
     const numFruits = await Promise.all(promises);
     const sum = numFruits.reduce((sum, fruit) => sum + fruit);

    console.log(sum)
     console.log('End')
    }

這個版本易于閱讀和理解,需要一秒鐘來計算水果總數。

JavaScript循環中怎么使用 async/await

從上面看出來什么

  1. 如果你想連續執行await調用,請使用for循環(或任何沒有回調的循環)。

  2. 永遠不要和forEach一起使用await,而是使用for循環(或任何沒有回調的循環)。

  3. 不要在 filterreduce 中使用 await,如果需要,先用 map 進一步驟處理,然后在使用 filterreduce 進行處理。

看完了這篇文章,相信你對JavaScript循環中怎么使用 async/await有了一定的了解,想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女