私はこの問題に何日も苦労してきましたが、それを処理するエレガントな方法がわかりません。これが問題です。
forEach ループを実行していますが、すべてがいつ完了したかを知る必要があります。forEach ループはブロックしているため、 forEach ループの後に a をドロップするだけで十分簡単console.log
です。これは、 forEach ループが完了したときに実行されます。ただし、forEach ループ内に同期していない関数がある場合、このシステム全体がすぐに機能しなくなり、非常に奇妙なハッキー カウンターと if ステートメント以外に、ループの内容がいつ完了したかを知る方法がありません。私の質問は、JavaScript でこの状況を処理するエレガントな方法があるかどうかです。
以下にいくつかの例を示します。
この場合、ループ内のすべてが同期されるため、forEach ループは完全にうまく機能します。
[1,2,3].forEach(function(num){
console.log("we're on " + num);
});
console.log('done counting!')
//=> we're on 1
//=> we're on 2
//=> we're on 3
//=> done counting!
ただし、基本的な例として、ここで問題が発生し始めます。
[1,2,3].forEach(function(num){
setTimeout(function(){ console.log(num) }, 200);
});
console.log('done counting!');
//=> done counting!
//=> we're on 1
//=> we're on 2
//=> we're on 3
これが起こっていることは理にかなっていますが、カウントが完了したときにコールバックが必要であるという不幸な問題を抱えており、次のようなひどいもの以外にコールバックをスムーズに行う方法はありません。
var counter = 0;
var numbers = [1,2,3]
var log_number = function(num){
console.log("we're on " + num);
counter++;
if (counter == numbers.length) {
console.log("done counting!")
}
}
numbers.forEach(function(num){
setTimeout(log_number(num), 200);
});
//=> we're on 1
//=> we're on 2
//=> we're on 3
//=> done counting!
よかった、それは非常に多くのオーバーヘッドです。これを実現するよりスムーズな方法はありますか?promise、deferred、およびシーケンスをチェックアウトしましたが、これをより簡潔にする方法でそれらのいずれかを実際に実装することはできませんでした:(
明確にするために、特に私の問題は setTimeout ではありません。一般に、同期関数内で非同期関数が実行されています。これは最も単純な例にすぎません。