點燈坊

失くすものさえない今が強くなるチャンスよ

使用 for await of 處理 Array Promise

Sam Xiao's Avatar 2021-10-30

當 ECMAScript 2015 引進 Promise 概念後,實務上會遇到 Array Promise,若要搭配 ECMAScript 2017 的 async await,可使用 for await of 讓 Codebase 更精簡。

Version

ECMAScript 2017

Imperative

let data = [
  Promise.resolve (1),
  Promise.resolve (2)
]

for (let x of data)
  console.log (x)

第 1 行

let data = [
  Promise.resolve (1),
  Promise.resolve (2)
]

data 為 Array,但其 element 都是 Promise。

第 6 行

for (let x of data)
  console.log (x)

若想印出 Array 中 Promise 內的值,直覺會使用 for loop 搭配 console.log

await000

但這樣寫不會印出 12

await

let data = [
  Promise.resolve (1),
  Promise.resolve (2)
]

for (let x of data)
  console.log (await x)

第 6 行

for (let x of data)
  console.log (await x)

若要 console.log 印出 Promise 內部值,必須在每個 x 前加上 await 從 Promise 內取出。

await001

for await of

let data = [
  Promise.resolve (1),
  Promise.resolve (2)
]

for await (let x of data)
  console.log (x)

ES2017 提供了 for await of,如此 x 已經從 Promise 中取出,console.log 可直接使用。

await002

Promise.all

let data = [
  Promise.resolve (1),
  Promise.resolve (2)
]

let show = a => a.forEach (x => console.log(x))

Promise
  .all (data)
  .then (show)

若不想使用 async await,對於 Array Promise 可先使用 Promise.all 處理,如此 Array Promise 中的值會先從 Promise 取出,唯 Promise.all 回傳為新的 Promise,且仍然是 Array,因此再使用 then 解開才能搭配 forEachconsole.log 印出。

await003

Promise.all + await

let data = [
  Promise.resolve (1),
  Promise.resolve (2)
]

for (let x of await Promise.all (data))
  console.log (x) 

Promise.all 回傳為 Promise,因此也可使用 for of await 先將 Promise.all 回傳結果解開,如此就可繼續使用 for of

await004

Conclusion

  • for await of 比原本 for of 寫法優雅,且 {} 可直接使用 x,不必再一直重複 await

  • 若不喜歡使用 await,Array Promise 可先用 Promise.all 處理,別忘了其回傳仍是 Promise,因此必須接著使用 then 才能取得 Promise 內部值

  • for await offor of await 不太一樣,for await of 是搭配 Array Promise;而 for of await 是搭配 Promise Array

Reference

MDN, for await…of