javascript – 如何在循环中处理异步Node.js.

我有这样一个循环:

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操作往往更容易陷入僵局.

上一篇:在Linux和Windows计算机之间同步Eclipse项目


下一篇:java – 双重检查锁定 – 陷阱?