2012-01-13 50 views
2

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

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

所以,让我们尝试实现我们deleteAll方法(实际上它是从节点MongoDB的原生驱动一个真正的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); 
    } 
}; 
+0

你有'each'方法的源代码吗?如果你有这个问题,应该很容易找到你。 – hugomg 2012-01-13 16:54:09

回答

0

那么你写了什么工作,虽然不知道这行:

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

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

+0

嗯,是的,它是有点作品,但'collection.remove'将被并行执行而不是串行执行,并且最终的回调可能会在某些'collection.remove'完成之前触发。 – 2012-01-13 17:23:15

1

尝试类似这样的事情。

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'); 
     }) 
     }  
    } 
    }) 
} 
1

所以,一对夫妻带着节点几个月后,我得到了回答我的问题,这里是一个可能实现的异步每个(可能还有其他的类似,但在错误处理细微差别):

​​

mongo中each的实现是不同的,它不可能用它做适当的顺序迭代(也许它没关系,也许他们有不同的设计目标)。