状況は次のとおりです。node.jsを初めて使用し、次のようなマルチレベルのjsonファイルを含む40MBのファイルがあります。[{}、{}、{}]これはオブジェクトの配列(〜7000オブジェクト)です。各オブジェクトにはプロパティがあり、それらのプロパティの1つはオブジェクトの配列でもあります
ファイルの内容を読み取って反復する関数を作成しました。使いやすさではなく、内容的には欲しいものを手に入れることができました。配列を反復しながらノードが他のWebリクエストを処理できるようにする非同期関数を作成したと思いましたが、そうではありません。誰かが私が間違ったことを教えてくれて、それを書き直して非ブロッキングの反復を行うことができれば、とてもありがたいです。この状況を処理する関数は次のとおりです。
function getContents(callback) {
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
js = JSON.parse(data);
callback();
return;
});
}
getContents(iterateGlobalArr);
var count = 0;
function iterateGlobalArr() {
if (count < js.length) {
innerArr = js.nestedProp;
//iterate nutrients
innerArr.forEach(function(e, index) {
//some simple if condition here
});
var schema = {
//.....get props from forEach iteration
}
Model.create(schema, function(err, post) {
if(err) {
console.log('\ncreation error\n', err);
return;
}
if (!post) {
console.log('\nfailed to create post for schema:\n' + schema);
return;
}
});
count++;
process.nextTick(iterateGlobalArr);
}
else {
console.log("\nIteration finished");
next();
}
上記の状況をどのようにテストしたかは明らかです。2つのタブを開きます。1つはこの反復をロードしますが、これには時間がかかり、2つ目は、反復が終了するまでロードされない別のノードルートを使用します。だから本質的に私はブロッキングコードを書いたが、それをリファクタリングする方法がわからない!コールバックですべてが発生しているという理由だけで、別のリクエストを処理するためにイベントループを解放できないのではないかと思います...
あなたのコードはほぼ正しいです。あなたがしているのは、うっかりしてすべてのアイテムを次のティックに追加することです...それでもブロックされます。
重要なコードは次のとおりです。
Model.create(schema, function(err, post) {
if(err) {
console.log('\ncreation error\n', err);
return;
}
if (!post) {
console.log('\nfailed to create post for schema:\n' + schema);
return;
}
});
// add EVERYTHING to the very same next tick!
count++;
process.nextTick(iterateGlobalArr);
getContents()が実行され、カウントが0のときに、イベントループのティックAにいるとします。iterateGlobalArrと入力し、Model.createを呼び出します。Model.createは非同期であるため、すぐに戻り、process.nextTick()はアイテム1の処理を次のティック(たとえばB)に追加します。次にiterateGlobalArrを呼び出します。これは同じことを行い、アイテム2を次のティックに追加します。ティック、これはまだBです。次に項目3、というように続きます。
あなたがする必要があるのは、カウントインクリメントとprocess.nextTick()をModel.create()のコールバックに移動することです。これにより、nextTickが呼び出される前に現在のアイテムが処理されるようになります...つまり、モデルアイテムが作成された後、次のアイテムが実際に次のティックに追加されます...これにより、アプリはその間に他のものを処理する時間を確保できます。iterateGlobalArrの修正バージョンは次のとおりです。
function iterateGlobalArr() {
if (count < js.length) {
innerArr = js.nestedProp;
//iterate nutrients
innerArr.forEach(function(e, index) {
//some simple if condition here
});
var schema = {
//.....get props from forEach iteration
}
Model.create(schema, function(err, post) {
// schedule our next item to be processed immediately.
count++;
process.nextTick(iterateGlobalArr);
// then move on to handling this result.
if(err) {
console.log('\ncreation error\n', err);
return;
}
if (!post) {
console.log('\nfailed to create post for schema:\n' + schema);
return;
}
});
}
else {
console.log("\nIteration finished");
next();
}
}
また、iterageGlobalArrを呼び出すたびに、jsを渡してカウンターすることを強くお勧めします。これにより、iterateGlobalArrのデバッグが非常に簡単になりますが、それは別の話です。
乾杯!
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加