javascript - Node js 异步和等待的嵌套循环

标签 javascript arrays node.js mongoose async-await

我的问题是如何在 Node Js 中编写嵌套循环

我的代码是

var result = db.data;
var FirstArray= new Array();
var SecondArray= new Array();
GetUserData();
async function GetUserData(){
    for (let info of result) {
         await getUserInfo(info);
    }
    res.send({status:"True", data: FirstArray, newdata:SecondArray  });
 }
    function getUserInfo(info){
        return new Promise(( resolve, reject )=>{
             UserModel.UserType.findOne({'_id': info.UserId }, usersProjection, function(err, UserData) {
                 if(err) {
                    res.send({status:"Fale", Error:err });
                    reject(err);
                 } else {
                        var data = UserData;
                        FirstArray.push(data);
                        GetUser();
                        async function GetUser(){
                           for (let newinfo of data ) {
                               await getnewUserInfo(newinfo);
                           }
                       }
                       function getnewUserInfo(newinfo){
                          return new Promise(( resolve, reject )=>{
                             UserModel.UserTypeNew.findOne({'_id': newinfo.UserId }, usersProjection, function(newerr, UserData) {
                               if(newerr) {
                                   res.send({status:"Fale", Error:newerr });
                                   reject(err);
                              } else {
                                  SecondArray.push(UserData)
                                 resolve();
                               }
                            });
                         });
                       }
                 }
             });
        });
     }

我将仅获取第一个循环详细信息如何获取第二个循环详细信息。

还建议其他方法。

那么哪种方法是嵌套循环的最佳实践。

最佳答案

由于 Mongoose 应该返回 promise ,因此您不需要新的 promise 。您可以使用 map 将数据映射到 Promise,然后使用 Promise.all 等待它们同时执行。您当前的代码将逐个执行查询(仅当当前代码完成时才执行下一个查询)。这是不需要的并且非常慢。

因此您可以将 db.data 映射到 [[first,second],[first,second],...]。我不映射 findOne 的结果,因为它不应该返回一个数组,并且觉得很奇怪 resultOfFindOne 的某些内容实际上有效,因为 findOne 应该返回一个文档或 null。

UserModel.UserType.findOneUserModel.UserTypeNew.findOne 都尝试通过 _id 查找一条记录,并且都使用相同的 _id,因此不需要执行 UserType 查询,然后当返回执行 UserTypeNew 查询时,您只需使用 info.UserId 进行这两个查询。

const GetUserData = (result) => 
  Promise.all(
    result.map(info=>getUserInfo(info))
  ).then(
    results=>{//results should be [[first,second],[first,second],...]
      let [FirstArray,SecondArray] = results.reduce(
        ([allFirst,allSecond],[first,second])=>
          [allFirst.concat([first]),allSecond.concat([second])],
        [[],[]]
      );
      res.send({ status: "True", data: FirstArray, newdata: SecondArray })
    }
  ).catch(
    err=>
      res.send({status:"Fale", Error:err })
  );
const getUserInfo = info =>
  //mongoose can return promises, no need to convert callback api to promise:
  //http://mongoosejs.com/docs/queries.html
  Promise.all([
    UserModel.UserType.findOne({ '_id': info.UserId }, usersProjection).exec(),
    UserModel.UserTypeNew.findOne({ '_id': info.UserId }, usersProjection).exec()
  ]);
//when using const the function is not hoisted so you can't call a function
//  before it was declared.
GetUserData(db.data);

如果您使用的是旧版本的 mongoose(不是 5.xxx),您可能仍然需要将基于回调的 api 转换为 Promise,它看起来有点像这样:

const asPromise = object => fn => args =>
  new Promise(
    (resolve,reject)=>
      fn.apply(
        object,
        args.concat([
          (...result)=>
            (result[0])//first argument of callback is error
              ? reject(result[0])//reject with error
              : resolve(result.slice(1,result.length))//resolve with result(s)
        ])
      )
  );

const newUserType = asPromise(UserModel.UserTypeNew);
const userType = asPromise(UserModel.UserType);

//making a query with callback but convert it to promise
newUserType(UserModel.UserTypeNew.findOne)([
  { '_id': info.UserId }, usersProjection
]).then(//this will resolve as array, only need first item
  ([result])=>result
);    

userType(UserModel.UserType.findOne)([//note that I'm not passing UserModel.UserTypeNew.findOne
  { '_id': info.UserId }, usersProjection
]).then(//this will resolve as array, only need first item
  ([result])=>result
);

关于javascript - Node js 异步和等待的嵌套循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48592155/

相关文章:

javascript - 使用 javascript 填充动态表单

javascript - 将多个值从 onclick 函数发送到 jquery 函数

node.js - $geoWithin 查询形式 mongodb 到 mongoose 语句

javascript - Firebase 功能正在部署,但未显示在控制台中

javascript - 从用户 Javascript 获取 int

c++ - C++:如果我想在数组中输入一系列数字,而不受我需要输入的数字量的限制。我应该怎么做?

javascript - 在数组中动态添加变量

java - 游戏UNO java代码设计

javascript - AngularJS + NodeJS 路由 - 不起作用

javascript - 如何在带有 Electron 和 NodeJs 8 的 Angular 7 中通过 Jest 迁移或使用现有的 karma Jasmine