【问题标题】:Node.js async module issueNode.js 异步模块问题
【发布时间】:2013-11-09 19:36:38
【问题描述】:

我正在尝试使用异步模块来减少特定于 Node.js 的“回调地狱”。基本上,我正在尝试使用async.series 从数据库中检索一些信息并将其显示在我的视图中。不过,在我看来,我没有得到任何结果。

这是我目前的代码:

// Search
exports.search = function(req, res) {

    var x = [];



        async.series([
            function(cb) {
                Lang.find({ lang: req.query.keyword }).sort({ verbal: -1 }).exec(function(err, langs) {              

                    cb(null, langs);

                });
            },

            function(cb) {
                Human.find({}, function(err, humans) {            

                    cb(null, humans);
                });
            }], 

            function(err, results) {
                if (err) {
                    res.send(500);
                }

                for(var i = 0; i < results[0].length; i++) {
                    for(var j = 0; j < results[1].length; j++) {
                        if(results[1][j]._id == results[0][i].human) {
                             x.push(results[1][j]);
                        }
                    }
                } 

                res.render('myView', { title: 'Search Results', humans: x });
            }
        );
    }

我首先要查询 Lang 模型 (MongoDB) 并找到匹配 req.query.keyword 的记录。之后,我想查询人类模型并找到所有具有特定语言技能的人类。此外,FOR 循环旨在消除我的数组中的重复项,因为人类可能有多种语言。

【问题讨论】:

    标签: javascript node.js mongodb asynchronous express


    【解决方案1】:

    如果我正确理解您的代码,您可能想改用async.waterfall。它将一个函数的结果作为参数传递给下一个函数。还有一些其他的优化可以做:

    async.waterfall([
      function(done) {
        Lang
          .find({ lang: req.query.keyword })
          .sort({ verbal: -1 }) // (not really useful)
          .select('human')      // not strictly necessary, but saves a bit of space
          .exec(done);          // short for : 
                                //   .exec(function(err, results) {
                                //     done(err, results);
                                //   });
      },
      function(langs, done) {
        // extract the 'human' property from each result
        var _ids = langs.map(function(lang) {
          return lang.human;
        });
    
        // perform a query finding all humans in the list of ids
        Human
          .find({ _id : { $in : _ids } })
          .exec(done);
      }
    ], function(err, humans) {
      if (err)
        return res.send(500);
      res.render('myView', {
        title : 'Search Results',
        humans: humans
      });
    });
    

    编辑:因为$in 不保留顺序,而this answer 建议使用$or 将,尝试将此作为第二个查询的替代方案:

      ...
      function(langs, done) {
        var query = langs.map(function(lang) {
          return { _id : lang.human };
        });
    
        Human
          .find({ $or : query })
          .exec(done);
      }
      ...
    

    【讨论】:

    • 刚刚试用了您的代码,它运行良好!尽管如此,降序功能是因为我希望根据他们的语言技能以降序返回结果。因此,例如,如果我有 2 个英语技能为 5 和 10 的人,我希望具有 10 的人成为搜索结果列表中的第一个。这个 sn-p 按照它找到的顺序返回人类列表。
    • @shinpou 如果订单正在导入,我不完全确定使用$in 是否会使其保持有序。所以请测试:)
    • 我试过了,但订单不是我要找的那个:(但仍然!我得到了正确的结果!非常感谢!不过,你能指出一些吗方向(文档)或者解释done回调函数。是简单的集成在瀑布函数中,用来给下一个函数传参数吗?
    • @shinpou done 回调与您调用的cb 相同(我通常将其称为done,但您可以给它任何您想要的名称)。我在代码中添加了一些额外的 cmets 以使其更清晰。
    • 有什么方法可以让 _ids 数组根据 lang.verbal 升序排列?我可以用 lang.human 和 lang.verbal 构建一个二维数组,然后生成一个按升序排列的新数组吗?
    猜你喜欢
    • 2023-03-04
    • 1970-01-01
    • 2012-12-04
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2015-02-19
    • 1970-01-01
    相关资源
    最近更新 更多