如何在另一个异步`each`方法(NodeJS)内部进行异步方法调用

How to make async method call inside of another async `each` method (NodeJS)?

本文关键字:内部 调用 异步方法 NodeJS 方法 另一个 异步 each      更新时间:2023-09-26

如何在另一个异步each方法(NodeJS)内部进行异步方法调用?

具体的例子——使用数据库时,我需要删除所有记录。但我不能只是删除整个集合,我需要逐一销毁每一条记录,在删除之前,我需要读取记录,在应用程序中执行一些业务逻辑,然后删除它。

因此,让我们尝试实现我们的deleteAll方法(实际上它是来自node-mongodb-native驱动程序的一个真正的API):

deleteAll = function(selector, callback){
  collection.find(selector).each(function(err, doc){
    if(err){
      callback(err)
    }else{
      if(doc === null){
        // each returns null when there's no more documents, we are finished.
        callback(null)      
      }else{
        doSomeBusinessLogicBeforeDelete(doc)
        // How to delete it using asynchronous `remove` method?        
        collection.remove({_id: doc._id}, function(err){
          // What to do with this callback? 
          // And how to make `each` wait untill we 
          // deleting this record?
          ???
        })
      }      
    }
  })
}

实际上有一种方法可以做到这一点——使用collection.nextObject方法而不是collection.each,但我想知道使用each是否可以解决这个问题?现在我相信这是不可能的,但也许我错了?

UPDATE:each方法的来源:

Cursor.prototype.each = function(callback) {
  var self = this;
  if (!callback) {
    throw new Error('callback is mandatory');
  }
  if(this.state != Cursor.CLOSED) {
    process.nextTick(function(){
      // Fetch the next object until there is no more objects
      self.nextObject(function(err, item) {        
        if(err != null) return callback(err, null);
        if(item != null) {
          callback(null, item);
          self.each(callback);
        } else {
          // Close the cursor if done
          self.state = Cursor.CLOSED;
          callback(err, null);
        }
        item = null;
      });
    });
  } else {
    callback(new Error("Cursor is closed"), null);
  }
};

试试这样的方法。

deleteAll = function(selector, callback){
  // count all documents you need to fire remove for
  var count = collection.filter(function(doc) { return doc === null }).length,
          i = count;
  collection.find(selector).each(function(err, doc){
    if(err){
      callback(err)
    }else{
      if(doc === null){
        callback(null)      
      }else{
        doSomeBusinessLogicBeforeDelete(doc)
        collection.remove({_id: doc._id}, function(err){
          i--;
          if (i <= 0) callback('done');
        })
      }      
    }
  })
}

因此,在使用node几个月后,我得到了问题的答案,这里是异步的一种可能实现(可能还有其他类似的实现,但在错误处理方面略有不同):

asyncEach(
  function(obj, next){
    // do something with obj
    // call next when You finish and want next object, 
    // You can also pass error into next in case of error.
    console.log(obj)
    next()
  },
  function(err){
    // Will be called when there's no more objects.
  }
)

在mongo中实现each是不同的,用它不可能进行适当的顺序迭代(也许可以,也许他们心中有不同的设计目标)。

好吧,你写的会起作用,尽管不确定这一行:

  if(doc === null){
    // each returns null when there's no more documents, we are finished.
    callback(null)  

因为,我不知道其中的逻辑,但这会起作用。从技术上讲,函数不会等待,您只需传递另一个函数,该函数将在工作完成时执行。这里所做的是异步和并行的。您还可以查看异步模块中每个函数和其他一些函数的异步版本。