Node.js 如何让cursor.forEach()迭代器等待承诺链解析?

Node.js 如何让cursor.forEach()迭代器等待承诺链解析?,node.js,mongodb,node-mongodb-native,Node.js,Mongodb,Node Mongodb Native,使用node.jsmongodbnative模块,我试图使用promisified迭代器,但在触发finalCallback db.collection('items').find({}).forEach(promiseIterator, finalCallback); function promiseIterator(doc){ return Promise.resolve(doc) .then(res => { console.log(

使用node.js
mongodb
native模块,我试图使用promisified迭代器,但在触发
finalCallback

db.collection('items').find({}).forEach(promiseIterator, finalCallback);

function promiseIterator(doc){
    return Promise.resolve(doc)
        .then(res => {
            console.log(res); // this fires *after* finalCallback fires
        })
}

function finalCallback(res){
    console.log(res); // this fires *before* promiseIterator resolves all promise chains
}
文件在这里:

他们的ES6示例都使用生成器,所以我不确定承诺在这里是否有效。但在启动finalCallback之前,承诺链还没有完全解决


出现此问题的原因是我的
promisediator
需要对每个文档进行几个异步/promisified调用。(我无法使用
.toArray()将所有文档加载到内存中)
因为有超过一百万个文档,当我尝试这样做时,我遇到了一个
内存不足的进程
错误。

不幸的是,你不能。Mongodb native的forEach并没有像你所注意到的那样等待承诺的解决。它们只需要调用回调函数,然后继续下一个对象

光标的
forEach
源代码(第769行)

您需要使用
next
hasNext
手动迭代

编辑:添加了示例

您可以完全按照jstice4all成功的方式使用承诺

db.collection('items').find({}, (err, resultCursor) => {
  resultCursor.next(processItem);

  function processItem(err, item) {
    if(item === null) return; // All done!

    // Add your asynchronous function/chain of functions in place of Promise.resolve()
    Promise.resolve().then(() => {
      resultCursor.next(processItem); // Read next item from database
    });
  }
});
当然,这将一个接一个地连续处理所有对象。如果要并行处理所有对象并等待它们完成后再执行其他操作,则应使用“收集所有已创建的承诺”和
Promise.all


顺便说一句,
nextObject
已被弃用,因此您可以使用
next
代替它。

不幸的是,您不能。Mongodb native的forEach不会像您所注意到的那样等待承诺的解决。它们只需调用回调函数并继续下一个对象

光标的
forEach
源代码(第769行)

您需要使用
next
hasNext
手动迭代

编辑:添加了示例

您可以完全按照jstice4all成功的方式使用承诺

db.collection('items').find({}, (err, resultCursor) => {
  resultCursor.next(processItem);

  function processItem(err, item) {
    if(item === null) return; // All done!

    // Add your asynchronous function/chain of functions in place of Promise.resolve()
    Promise.resolve().then(() => {
      resultCursor.next(processItem); // Read next item from database
    });
  }
});
当然,这将一个接一个地连续处理所有对象。如果要并行处理所有对象并等待它们完成后再执行其他操作,则应使用“收集所有已创建的承诺”和
Promise.all


顺便说一句,
nextObject
已被弃用,因此您可以使用
next
来代替它。

您可以使用带有
nextObject
的递归来代替
forEach

db.collection('items').find({}, function(err, resultCursor) {
  function processItem(err, item) {
    if(item === null) {
      return; // All done!
    }

    externalAsyncFunction(item, function(err) {
      resultCursor.nextObject(processItem);
    });

  }

  resultCursor.nextObject(processItem);
}

您可以将递归与
nextObject
一起使用,而不是使用
forEach

db.collection('items').find({}, function(err, resultCursor) {
  function processItem(err, item) {
    if(item === null) {
      return; // All done!
    }

    externalAsyncFunction(item, function(err) {
      resultCursor.nextObject(processItem);
    });

  }

  resultCursor.nextObject(processItem);
}

你能提供一个例子吗?我试图从他们的文档中使用
yield
,但我得到了一个语法错误。我使用的是node v7。他们的文档没有任何承诺示例(我只看到生成器),但他们声称你可以使用它们。
externalAsyncFunction()在哪里
在您的示例中从调用?我的示例只是引用了jstice4all的示例,这似乎是正确的。与在Thia中复制示例相比,最好是引用该示例。我没有得到传递给
externalAsyncFunction
回调。我将jstice4all的示例与我的示例结合在一起。现在应该清楚了。您能提供示例吗?我尝试过了从他们的文档中使用
yield
,但我得到一个语法错误。我使用的是节点v7。他们的文档没有任何承诺示例(我只看到生成器),但他们声称您可以使用它们。
externalAsyncFunction()在哪里
在您的示例中从调用?我的示例只是引用了jstice4all的示例,这似乎是正确的。最好是引用该示例,而不是在thia中复制示例,因为我没有得到传递给
externalAsyncFunction
回调。我将jstice4all的示例与我的示例相结合。现在应该已经清楚了。是否可以使用h有
nextObject
?是的,只需从
然后
调用
nextObject
。您介意添加一个使用承诺的示例吗
.find()
和游标,而不是回调。我认为这是正确的答案,但我想使用承诺。这里可以将承诺与
nextObject
一起使用吗?是的,只需从
然后调用
nextObject
。您介意添加一个将承诺与
一起使用的示例吗。find()
和游标而不是回调。我认为这是正确的答案,但我想使用承诺。