【问题标题】:What's the proper way of chaining async functions in Node.js?在 Node.js 中链接异步函数的正确方法是什么?
【发布时间】:2012-03-01 04:02:57
【问题描述】:

我有一个有趣的案例,我需要使用 Mongoose 在 MongoDB 中进行一些查询,但是在我完成所有查询之前就返回了响应。

我有两种文档类型,列表和项目。在一个特定的调用中,我需要获取特定用户的所有列表,然后遍历每个列表并获取所有项目并将它们附加到适当的列表中,然后再返回。

List.find({'user_id': req.params.user_id}, function(err, docs){
  if (!err) {
    if (docs) {

      var results = [];

      _und.each(docs, function(value, key) {

        var list = value.toObject();
        list.items = [];

        Item.find({'list_id': value._id}, function(err, docs) {
          if (!err) {
            _und.each(docs, function(value, key) { list.items.push(value.toObject()); });
            results.push(list);
          }
          else {
            console.log(err);
          }
        });
      });

      res.send(results);

(_und 是我导入 underscore.js 的方式)

显然问题在于回调,由于有多个循环,我无法在回调中返回。

也许在这种情况下,我需要提前获取计数并在每次迭代时检查它以确定何时返回结果。但这似乎并不优雅。

【问题讨论】:

    标签: javascript node.js express mongoose


    【解决方案1】:

    代码解决方案

    首先问题在于代码。您在 Item.find 查询完成之前发送结果。你可以很容易地解决这个问题

    var count = docs.length + 1;
    next()
    _und.each(docs, function(value, key) {
    
        var list = value.toObject();
        list.items = [];
    
        Item.find({
            'list_id': value._id
        }, function(err, docs) {
            if (!err) {
                _und.each(docs, function(value, key) {
                    list.items.push(value.toObject());
                });
                // push asynchronous
                results.push(list);
                next()
            }
            else {
                console.log(err);
            }
        });
    });
    
    function next() {
        --count === 0 && finish()
    }
    
    function finish() {
        res.send(results)
    }​
    

    最简单的方法是引用计数,默认计数为文档数。然后,每次您完成获得一个项目时,您调用next 并将计数减一。

    一旦您完成所有项目,您的计数应该为零。请注意,我们执行.length + 1 并立即致电next。这与没有文件的情况相反,否则不会做任何事情。

    数据库解决方案

    最好的解决方案是正确使用 mongo。你不应该在你的代码中做有效的加入,它很慢而且效率很低。您应该有一个嵌套文档并非规范化您的列表。

    所以list.items = [Item, Item, ...]

    另外,请避免使用 mongoose,它效率低下,请使用本机 mongo 驱动程序。

    【讨论】:

      【解决方案2】:

      我使用这个模块: https://github.com/caolan/async

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多