情况如下:我是node.js的新手,我有一个40MB的文件,其中包含多层json文件,例如:[{},{},{}]这是一个对象数组(约7000个对象)。每个对象都有属性,其中一个属性也是对象的数组
我编写了一个函数来读取文件的内容并对其进行迭代。我成功地获得了我想要的内容,但没有可用性。我以为我写了一个异步函数,该函数将允许节点在迭代数组时服务于其他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();
}
这样就很清楚我是如何测试上述情况的。我打开两个选项卡,其中一个加载此迭代会花费一些时间,第二个选项卡是另一个节点路由,直到迭代结束才加载。因此,基本上我已经写了一个阻塞代码,但不确定如何重构它!我怀疑只是因为回调中发生了所有事情,所以我无法释放事件循环来处理另一个请求...
您的代码几乎是正确的。您正在做的是无意中将所有项目添加到下一个刻度...仍然阻塞。
重要的代码片段在这里:
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()运行且count为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();
}
}
还要注意,我强烈建议您传递js并在每次调用iterageGlobalArr时进行计数器处理,因为这将使您的iterateGlobalArr易于调试,除其他外,但这是另外一回事了。
干杯!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句