我有这样一个循环:
var i,j,temparray,chunk = 200;
for (i=0,j=document.mainarray.length; i<j; i+=chunk) {
temparray = document.mainarray.slice(i,i+chunk);
var docs = collection.find({ id: { "$in": temparray}}).toArray();
docs.then(function(singleDoc)
{
if(singleDoc)
{
console.log("single doc length : " + singleDoc.length);
var t;
for(t = 0, len = singleDoc.length; t < len;t++)
{
fs.appendFile("C:/Users/x/Desktop/names.txt", singleDoc[t].name + "\n", function(err) {
if(err) {
return console.log(err);
}
});
}
}
});
}
循环迭代两次.在第一次迭代中,它获得200个元素,其次,它获得130个元素.当我打开.txt文件时,我只看到130个名字.我想因为Node.js的异步性质,只处理数组的第二部分.我该怎么做才能处理数组的所有部分?提前致谢.
编辑:我终于将代码转为:
var generalArr = [];
var i,j,temparray,chunk = 200;
for (i=0,j=document.mainarray.length; i<j; i+=chunk) {
temparray = document.mainarray.slice(i,i+chunk);
generalArr.push(temparray);
}
async.each(generalArr, function(item, callback)
{
var docs = collection.find({ id: { "$in": item}}).toArray();
docs.then(function(singleDoc)
{
if(singleDoc)
{
console.log("single doc length : " + singleDoc.length);
var t;
for(t = 0, len = singleDoc.length; t < len;t++)
{
fs.appendFile("C:/Users/x/Desktop/names.txt", singleDoc[t].name + "\n", function(err) {
if(err) {
return console.log(err);
}
});
}
}
});
callback(null);
})
当我更改此行时:
var docs = collection.find({ id: { "$in": item}}).toArray();
到这一行:
var docs = collection.find({ id: { "$in": item}}).project({ name: 1 }).toArray();
它有效,我可以打印所有名称.我想在没有.project()的情况下尝试内存有问题.如何在不使用项目的情况下完成这项工作?我应该更改一些内存限制吗?提前致谢.
解决方法:
一旦你去异步你就不能回去了 – 你的所有代码都需要是异步的.在节点8中,您可以使用async和await关键字来处理此问题.在旧版本中你可以使用Promise – async / await只是它的语法糖.
但是,节点中的大多数API都比Promise早,因此它们使用回调.有一个promisify
函数可以将回调函数更新为promises.
有两种方法可以处理这种情况,您可以让所有异步操作同时发生,或者您可以将它们一个接一个地链接起来(保留顺序但需要更长时间).
因此,collection.find是异步的,它需要一个回调函数或返回一个Promise.我将假设您使用的API执行后者,但您的问题可能是前者(在这种情况下查找promisify).
var findPromise = collection.find({ id: { "$in": item}});
现在,此时findPromise保持正在运行的查找操作.我们说这是一个解析(成功完成)或拒绝(抛出错误)的承诺.我们想要在完成后将一个动作排队,然后我们这样做:
// The result of collection.find is the collection of matches
findPromise.then(function(docs) {
// Any code we run here happens asynchronously
});
// Code here will run first
在承诺内部,我们可以返回进一步的承诺(允许它们被链接 – 完成一个异步,然后完成下一个,然后一旦完成就解雇最终解决方案)或使用Promise.all让它们全部并行发生并在完成后解决:
var p = new Promise(function(resolve, reject) {
var findPromise = collection.find({ id: { "$in": item}});
findPromise.then(function(docs) {
var singleDocNames = [];
for(var i = 0; i < docs.length; i++) {
var singleDoc = docs[i];
if(!singleDoc)
continue;
for(var t = 0; t < singleDoc.length; t++)
singleDocNames.push(singleDoc[t].name);
}
// Resolve the outer promise with the final result
resolve(singleDocNames);
});
});
// When the promise finishes log it to the console
p.then(console.log);
// Code inline here will fire before the promise
使用async / await在节点8中更容易:
async function p() {
// Await puts the rest of this function in the .then() of the promise
const docs = await collection.find({ id: { "$in": item}});
const singleDocNames = [];
for(var i = 0; i < docs.length; i++) {
// ... synchronous code unchanged ...
}
// Resolve the outer promise with the final result
return singleDocNames;
});
// async functions can be treated like promises
p().then(console.log);
如果你需要异步地将结果写入文本文件,有几种方法可以做到 – 你可以等到最后并写下所有这些,或者在每次查找后链接一个promise来写它们,尽管我发现并行IO操作往往更容易陷入僵局.