【问题标题】:Making multiple mongoose calls in parallel using async使用异步并行进行多个猫鼬调用
【发布时间】:2015-11-03 12:59:32
【问题描述】:

为此苦苦挣扎了一段时间,我似乎遗漏了一些非常明显的东西。举个例子。假设我想同时进行三个调用。为了使其成为一个简单的示例或易于测试,假设我们想要一个脚本,该脚本从 mongodb 询问以下信息。

我们希望找到以下信息: - 我们要列出每个索引的 ns - 我们要列出具有 _id 的用户 - 我们想列出每个索引的 ns 有一个键 (是的,你是对的,这是一组荒谬的查询,但它们会在每个 mongo 数据库上返回一些内容。)

因此,在 mongo db 上执行此操作的简单脚本是:

var mongoose = require("mongoose");
var morgan = require('morgan');             // log requests to the console (express4)
var async = require('async');
mongoose.connect('mongodb://localhost/admin');



var Indexes = mongoose.model('system.indexes', {
    name: String,
    ns: String
});
var Users = mongoose.model('system.users', {
    user: String
})


        Indexes.find().exec(function(err, docs){
            for( var doc in docs ){
                console.log("Got Index " + docs[doc].ns);
            }
        })
        Users.find({ _id: {$ne: null}}).exec(function(err, docs){
            for (var doc in docs){
                console.log("And user " + docs[doc].user );
            }
        })
        Indexes.find({ key : {$ne : null}}).exec(function(err, docs){
            for (var doc in docs) {
                console.log("And Index with a key " + docs[doc].ns);
            }
        })

但是如果我想使用异步,我该怎么做。 所以尝试了以下方法来并行运行它们:

var mongoose = require("mongoose");
var morgan = require('morgan');             // log requests to the console (express4)
var async = require('async');
mongoose.connect('mongodb://localhost/admin');



var Indexes = mongoose.model('system.indexes', {
    name: String,
    ns: String
});
var Users = mongoose.model('system.users', {
    user: String
})


/// So lets do it with async Map instead
var queries = [];
queries.push(Indexes.find().exec());
queries.push(Users.find({ _id: {$ne: null}}).exec());
queries.push(Indexes.find({ key : {$ne : null}}).exec());

async.parallel(queries, function(err, docs){
    console.log("I've done some stuff");
})

这给了我一个错误声明

task(_restParam(function (err, args) { ^ 类型错误:对象不是函数

但是有没有一种简单的方法来解决这个问题。如何使用异步映射或并行进行多个查找。

===== 继Jigars的精彩回复后,我们离答案更近了===== Jigars 很好的答案现在可以工作了,保留下面的东西 如果有人有同样的问题

/// So lets do it with async Map instead
var queries = [];
queries.push(function (cb) {
    try {
        result = Indexes.find().exec();
        cb(null, result);
    } catch(e) {
        cb(e);
    }
})

queries.push(function (cb) {
    try {
        result = Users.find({ _id: {$ne: null}}).exec();
        cb(null, result);
    } catch(e) {
        cb(e);
    }
})

queries.push(function (cb) {
    try {
        result = Indexes.find({ key : {$ne : null}}).exec();
        cb(null, result);
    } catch(e) {
        cb(e);
    }
})

async.parallel(queries, function(err, docs) {
    // if any query fails
    if (err) {
        throw err;
    }

    var res1 = docs[0]; // result of queries[0]
    for (var opts in res1){
        console.log("In res1 we got " + res1[opts])
    }
    var res2 = docs[1]; // result of queries[1]
    for (var opts in res2){
        console.log("In res2 we got " + res2[opts])
    }
    var res3 = docs[2]; // result of queries[2]
    for (var opts in res3){
        console.log("In res3 we got " + res3[opts])
    }
})

所以现在并行工作,只是没有返回我想要的。 res1、res2 和 res3 中的结果看起来像 js 代码:

【问题讨论】:

    标签: node.js asynchronous mongoose


    【解决方案1】:

    我们可以使用 async/await 如下代码。

    let queries = [];
        
          userIds.forEach(userId => {
            queries.push(async()=>await Users.find({_id:userId}))
          });
        
          Promise.all( queries).then(function(result) {
              // result is an array of responses here
              console.log("result", result);
              return result;
          }).catch(function(err) {
              console.log(err);
              return ;
          });
    

    【讨论】:

      【解决方案2】:

      您的 queries.push 命令应采用以下方式

      queries.push(function (cb) {
          Indexes.find().exec(function (err, docs) {
              if (err) {
                  throw cb(err);
              }
      
              // do some stuff with docs & pass or directly pass it
              cb(null, docs);
          });
      })    
      
      queries.push(function (cb) {
          Users.find({ _id: {$ne: null}}).exec(function (err, docs) {
              if (err) {
                  throw cb(err);
              }
      
              // do some stuff with docs & pass or directly pass it
              cb(null, docs);
          });
      })
      
      queries.push(function (cb) {
          Indexes.find({ key : {$ne : null}}).exec(function (err, docs){
              if (err) {
                  throw cb(err);
              }
      
              // do some stuff with docs & pass or directly pass it
              cb(null, docs);
          });
      })
      
      async.parallel(queries, function(err, docs) {
          // if any query fails
          if (err) {
              throw err;
          }
      
          var res1 = docs[0]; // result of queries[0]
          var res2 = docs[1]; // result of queries[1]
          var res3 = docs[2]; // result of queries[2]
      })
      

      async 接受多个以回调函数为参数的函数。每个功能完成后,您需要调用cb。 您还需要传递每个查询的结果值。当所有查询并行执行完毕后,同样会以数组形式返回给您

      【讨论】:

      • 真是好东西,比以前更接近工作了。但是, res1,2 和 3 包含 java 代码而不是响应。以你的例子并在我的问题中更新它。有些东西回来了,但似乎(我可能错了)它认为代码是函数的完整产品,而不是返回。
      • 根据您的编辑更新了答案。想法是完成所有异步功能并通过cb() 传递最终输出。您可以浏览异步文档,其中包含各种不错的示例。
      • 所以现在偷偷跟进,我到底如何将变量发送到推送中。尝试绑定但出现错误...
      猜你喜欢
      • 2017-02-22
      • 1970-01-01
      • 2023-04-08
      • 2019-01-22
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      相关资源
      最近更新 更多