如何在另一个异步“each”方法(NodeJS)中进行异步方法调用?

发布于 2024-12-26 18:33:30 字数 1826 浏览 0 评论 0原文

如何在另一个异步 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);
  }
};

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

Concrete example - working with a database, I need to delete all records.
But I can't just drop the whole collection, I need to destroy every record one by one, before deletion I need to read the record, perform some business logic in the app and only then delete it.

So, let's try to implement our deleteAll method (actually it's a real API from node-mongodb-native driver):

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?
          ???
        })
      }      
    }
  })
}

There's actually a way to do it - using the collection.nextObject method instead of collection.each, but I want to know is this possible to solve this using each or not? Right now I believe that it's not possible, but maybe I'm wrong?

UPDATE: the source of each method:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉态萌生 2025-01-02 18:33:30

尝试这样的事情。

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

Try something like this.

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');
        })
      }      
    }
  })
}
风柔一江水 2025-01-02 18:33:30

因此,在使用 Node 几个月后,我得到了问题的答案,这是 async every 的一种可能实现(可能还有其他类似的实现,但在错误处理方面存在细微差别):

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.
  }
)

Implementation of each in mongo 是不同的,它不可能进行适当的顺序迭代(也许没关系,也许他们有不同的设计目标)。

So, after a couple of months with node, I got answer for my question, here's one possible implementation of async each (there may be other similar but with minor differences in error handling):

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.
  }
)

Implementation of each in mongo is different, it's impossible with it to do proper sequential iteration (maybe it's ok, maybe they have different design goals in mind).

百思不得你姐 2025-01-02 18:33:30

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

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

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

Well what you wrote will work, although not sure about this line:

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

Since, I don't know the logic, but that will work. Technically the functions don't wait, you just pass another function, which will be executed when the work finished. what is being done is async and parallel here. You can also have a look at the async version of each and some other functions in async module.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文