【TypeScript】Promise.allをmapで使う
- TypeScript 3.5.1
Promise.all()
の理解が曖昧だった。
const asyncFunc = async (prefix: string): Promise<void> => { return new Promise(resolve => { setTimeout(() => { console.log(`${prefix}_1秒待ちました`) return resolve() }, 1000) }) } const main = async () => { const prefixes = ['A', 'B', 'C', 'D', 'E'] const asyncFuncs: Promise<void>[] = [] for (const prefix of prefixes) { asyncFuncs.push(asyncFunc(prefix)) // 実行開始 } console.log('Promise.all前') await Promise.all(asyncFuncs).then(() => console.log('完了')) // すべてPromiseを返すまで待つ console.log('Promise.all後') } main()
こんなサンプルを書いてみた。
勘違いしていたのが、実は asyncFuncs.push(asyncFunc(prefix))
の段階ですでに実行は始まっているという点。
await Promise.all
の箇所で実行開始するのかと思っていたが、あくまでこいつは引数配列に含むすべてのPromiseが返ってくるのを待つという動作をする。
その証拠にこの行をコメントアウトしても console.log(
${prefix}_1秒待ちました)
は動作する。
そしてforを使わない方がかっこいいと思っているので、mapを使った場合。
const asyncFunc = async (prefix: string): Promise<void> => { return new Promise(resolve => { setTimeout(() => { console.log(`${prefix}_1秒待ちました`) return resolve() }, 1000) }) } const main = async () => { const prefixes = ['A', 'B', 'C', 'D', 'E'] const asyncFuncs = prefixes.map(prefix => asyncFunc(prefix)) // 実行開始 console.log('Promise.all前') await Promise.all(asyncFuncs).then(() => console.log('完了')) // すべてPromiseを返すまで待つ console.log('Promise.all後') } main()
実行するとどちらも下のように動く。
$ yarn run ts-node main.ts yarn run v1.16.0 warning package.json: No license field Promise.all前 A_1秒待ちました B_1秒待ちました C_1秒待ちました D_1秒待ちました E_1秒待ちました 完了 Promise.all後 ✨ Done in 2.71s.