基本的に、非同期関数を含むforループがあります。問題は、プログラムがループの後に続くだけで、コードが続行する前にループで呼び出されたすべての非同期関数が終了するまで待機することです。
私のコードでは、「バー」は他のjson配列を含むjson配列です。
function write(bla) { // gets called one after another
for(var url in bla) {
asyncFunctionCall(url); // Executed about 50 times, it has to run parallel
}
// Wait for all called functions to finish before next stuff happens and
// write gets called again.
}
for(var foo in bar) {
// Here i parse the json array "foo" which is in the json array "bar"
write(foo[bla]); // bla is an array of multiple urls.
}
非同期関数呼び出しは次のようになります。
var request = require('request');
request(url, function (error, response, body) {
if(typeof response !== 'undefined') {
if((response.statusCode >= 400 && response.statusCode <= 451)
|| (response.statusCode >= 500 && response.statusCode <= 511))
return true;
return false;
}
return false;
});
ここで最も簡単な方法は、直接またはasync
/await
構文を介してプロミスを使用することです。この場合、おそらく直接。
まず、asyncFunctionCall
がプロミスを返すようにする必要があります。常にブール値を返すように見えるので、この場合は常にプロミスを解決します:
function asyncFunctionCall(url) {
return new Promise(resolve => {
request(url, function (error, response, body) {
if(typeof response !== 'undefined') {
if((response.statusCode >= 400 && response.statusCode <= 451)
|| (response.statusCode >= 500 && response.statusCode <= 511)) {
resolve(true);
return;
}
}
resolve(false);
});
});
}
次に、約束の配列を作成し、Promise.all
を使用して、すべての約束が完了するのを待ちます。これらの呼び出しは、並行して実行します:
function write(bla) { // gets called one after another
const promises = [];
for(var url in bla) {
promises.Push(asyncFunctionCall(url)); // Executed about 50 times.
}
return Promise.all(promises);
}
次に、write
からすべてのプロミスのチェーンを構築して、それらが連続して実行されるようにします。
let p = Promise.resolve();
for (const foo in bar) { // <== Notice `const`
// See "Edit" below
p = p.then(() => {
// Here i parse the json object "foo" in the json array "bar"
// bla is an array of multiple urls.
return write(foo[bla]));
});
}
const
コールバックが終了するため、そのループでlet
ではなくvar
ではなくfoo
またはthen
を使用することが重要であることに注意してください。 この質問の回答 を参照してくださいconst
およびlet
が機能する理由。
write
への各呼び出しは、前の作業が完了したときにのみ行われます。
次に、プロセス全体が完了するのを待ちます。
p.then(() => {
// All done
});
何も表示していませんsingwrite
のリクエストからのブール値ですが、write
からのプロミスの解決値として(配列として)利用可能です。
write
を呼び出すプロセスの2番目の部分は、論理フローをより明確にするasync
関数で記述することもできます。
async function doTheWrites() {
for (const foo in bar) {
// Here i parse the json object "foo" in the json array "bar"
// bla is an array of multiple urls.
await write(foo[bla]);
}
}
次に、全体的なプロセス:
doTheWrites().then(() => {
// All done
});
...またはこれがasync
関数でalsoの場合:
await doTheWrites();
関数を非同期にし、呼び出しを待機します。
async function write(foo) {
for(const url of foo) {
await asyncFunctionCall(url);
}
}
(async function() {
for(const foo of bar) {
await write(foo);
}
})()
それは次々にリクエストを実行します。それらを並行して実行するには、Promise.allを使用します。
const write = foo => Promise.all(foo.map(asyncFunctionCall));
Promise.all(bar.map(write))
.then(() => console.log("all done"));