如何在另一个异步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
来解决此问题?现在我相信这是不可能的,但也许我错了?
更新: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 :(得分: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 :(得分:1)
所以,经过几个月的节点,我得到了我的问题的答案,这里是每个async的一个可能的实现(可能有其他相似但在错误处理方面有细微差别):
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
的实现是不同的,使用它进行正确的顺序迭代是不可能的(也许它没关系,也许它们有不同的设计目标)。
答案 2 :(得分:0)
你写的内容会起作用,虽然不确定这一行:
if(doc === null){
// each returns null when there's no more documents, we are finished.
callback(null)
因为,我不知道逻辑,但那会起作用。从技术上讲,函数不会等待,您只需传递另一个函数,该函数将在完成工作时执行。这里做的是异步和并行。您还可以查看async模块中每个和其他一些函数的异步版本。