そのため、ループが正しい順序で実行されていないように見える理由に頭を悩ませようとしています。これは、値の並べ替えが完了したときにワーカースレッドによって行われる呼び出しです。
worker.on('message',function(data) {
console.log(data)
for (var i of data.entries) {
console.log(i.Email)
db.rota.checkUserHasShifts(i.Email,function(flag) {
if (flag) {
console.log('e', i.Email)
db.rota.getShiftsForUser(i.Email,function(err, shiftData) {
if (!shiftData) return
shiftData.Shifts = i.Shifts
shiftData.save(function(err) {
if (err) throw err;
})
})
} else {
console.log('n', i.Email)
var newShift = new db.rota({Email:i.Email,Shifts:i.Shifts})
newShift.save(function (err){
if (err) throw err
});
}
})
};
console.log("Spreadsheet processed")
})
20エントリのセットの場合、これは次のようになります。
{Email:"someemail",Shifts:{date:time}}
配列に20個のオブジェクトがある「data」オブジェクトを出力しますn [email protected]
、コンソールに20行、データベースに20の同一のエントリが表示されます。意図された動作は、明らかに、次のエントリに移動する前に各エントリを待機すること、または少なくともセット内の各電子メールのエントリをキューに入れることです。ループを待機させ、db.rota.checkUserHasShiftsメソッドを適切に実行し、最後のエントリだけでなくすべてのエントリに対してコールバックするにはどうすればよいですか?
呼び出す前にi変数のスコープを設定する必要があります。checkUserHasShifts
そうしないとi
、ループの最後の値で20回呼び出されます。
for (var i in items){
(function(i){ db.rota.checkUserHasShifts(i)..})(i);
}
理由を理解するために、この優れた記事のセクション6「スコープの再検討」が非常に役立つことがわかりました(ただし、C#のバックグラウンドを持つ人々を対象としています)。
https://mauricebutler.wordpress.com/tag/c-javascript/
関連する引用:
JavaScriptには「ブロックスコープ」がないため、forループは新しいスコープを導入していません。これは、要素変数にアクセスするたびに、同じメモリ位置が更新されることを意味します
このSOの質問は、その効果も非常によく示しています。ループ内のJavaScriptクロージャ–簡単な実用例
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加