console.log(call(0)); //配列を使ったその後の処理
これは動作しない。
Promiseも非同期処理なので、
一度非同期処理というイベントと関数の世界に足を踏み入れたら二度と帰ってこれない。
call関数の戻り値をPromise値で返すようにしてあげて、
call(0).then(fn)
という風に後続の処理を関数化して渡してやる必要がある。
並列処理で構わないならPromise.allがいいね。
イディオムを駆使して一撃で済ませるとこんな感じ。
JavaScript
1const fn1 = num => new Promise(resolve =>
2 setTimeout(() => resolve(num), 3000)
3);
4
5const call = num => Promise.all(
6 Array(5).fill(0).map((_, i) => num + i).map(fn1)
7);
8
9call(0).then(console.log);
10// Promise {<pending>}
11// 3秒待ってから: [0, 1, 2, 3, 4]
問題は直列処理。
こんな風に.then
メソッドを叩きながら数珠つなぎにしていく
JavaScript
1// 長いので500ms間隔に変更
2const fn1 = num => new Promise(resolve =>
3 setTimeout(() => resolve(num), 500)
4);
5
6const call = num => {
7 // とりま空のPromiseを宣言
8 let promise = Promise.resolve(null);
9 const results = [];
10 for (let i = 0; i < 5; i++) {
11 // このように代入していかないと直列繋ぎで実行してくれない
12 promise = promise.then(() =>
13 fn1(num + i).then(it => results.push(it))
14 )
15 }
16 // やる事が全部終わったら結果をresultsにすげ替える
17 return promise.then(() => results);
18}
19
20call(0).then(console.log);
21// Promise {<pending>}
22// 500ms*5の約2.5秒ほど待ってから: [0, 1, 2, 3, 4]
実はES2017で追加されたasync/awaitという糖衣構文でPromiseを同期処理っぽく書く事が出来る。
Lhankor_Mhyさんの回答はその書き方であり、普通にfor文で処理出来るようになる。
JavaScript
1// やはり長いので500msに
2const fn1 = num => new Promise(resolve =>
3 setTimeout(() => resolve(num), 500)
4);
5
6// なんだこの平易なコードは!?
7const call = async num => {
8 const results = [];
9 for (let i = 0; i < 5; i++) {
10 results.push(await fn1(num + i));
11 }
12 return results;
13};
14
15call(0).then(console.log);
16// Promise {<pending>}
17// 500ms*5の約2.5秒ほど待ってから: [0, 1, 2, 3, 4]
このasync版のcall
関数は上記のコードとほぼ同様の動きをしてくれる。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/22 08:49
2019/02/22 21:00 編集
2019/02/23 00:08
2019/02/23 02:35