JavaScript 非同期処理 Promiseをループする
JavaScriptで複数のリソースの読み込みやWebスクレイピング等によるリソース取得時に「XMLHttpRequest」を使い非同期で読み込みたい時があります。
最近ではPromiseで非同期処理をするのが一般的ですがfor
の中にPromiseを入れても意味がありません。
for(i=0; i < 10; i++){
let a = new Promise((resolve, reject)=>{
setTimeout(()=>{
console.log("foo");
return resolve();
})
})
}
console.log("bar");
Output
bar
foo(10)
この様にPromise自体は実行されますが、forの中身が実行されている間に次のconsole.log("bar");
が実行されてしまいます。
解決方法
条件が合うまで同じ関数を呼び出す方式でループを実現します。
function PromiseLoop(a, c, b = 0){
if(b >= a){
return Promise.resolve();
}else{
return c(b).then(()=>{
return PromiseLoop(a, c, b + 1);
});
}
}
- a : 繰り返し回数
- c : 関数 (戻り値は
Promise.resolve()
である必要がある) - b : 条件初期化
引数c
にはreturnにPromise.resolve()
を返す必要があります。
Promiseを返さないとthen()
で次の処理が動きません。
return c(b).then(()=>{
return PromiseLoop(a, c, b + 1);
});
引数b
は特に指定が無い限り初期値を0
に初期化します。
これは省略可能な引数です。
使用例
これは関数を10回繰り返すサンプルです。
PromiseLoop(10, (index)=>{
console.log(`foo${index}`);
return Promise.resolve();
}).then(()=>{
console.log("END");
});
Output
foo0
foo1
foo2
・・・
foo9
END
第三引数b
を変えて繰り返す範囲を絞る事も可能です。
これは配列の特定の要素範囲をロードする際に活用出来ます。
PromiseLoop(10, (index)=>{ // 5 >= 10
console.log(`foo${index}`);
return Promise.resolve();
}, 5).then(()=>{
console.log("END");
});
コメント
コメントを投稿