带有多个猫鼬查找的foreach循环后的javascript承诺

Posted

技术标签:

【中文标题】带有多个猫鼬查找的foreach循环后的javascript承诺【英文标题】:javascript promise after foreach loop with multiple mongoose find 【发布时间】:2019-05-22 14:59:04 【问题描述】:

我正在尝试使用一些 db 调用进行循环,一旦它们全部完成,就会发送结果。 - 使用一个承诺,但如果我在回调之后有我的承诺,它就不起作用。

  let notuser = [];


  let promise = new Promise((resolve, reject) => 

  users.forEach((x) => 


    User.find(
      /* query here */
    , function(err, results) 
        if(err) throw err

    if(results.length) 
          notuser.push(x);
          /* resolve(notuser)  works here - but were not done yet*/ 
        
    )
  );

  resolve(notuser); /*not giving me the array */

).then((notuser) => 

return res.json(notuser)

)

我该如何处理?

【问题讨论】:

映射查询承诺数组并使用Promise.all() 【参考方案1】:

下面是一个名为findManyUsers 的函数,它可以满足您的需求。 Mongo find 会返回一个 Promise 给你,所以只需在循环中收集这些 Promise 并与 Promise.all() 一起运行它们。所以你可以看到它的实际效果,我添加了一个模拟 User 类,它带有一个返回 promise 的 find 方法......

// User class pretends to be the mongo user. The find() method
// returns a promise to 'find" a user with a given id
class User 
    static find(id) 
        return new Promise(r => 
            setTimeout(() => r( id: `user-$id` ), 500);
        );
    


//  return a promise to find all of the users with the given ids
async function findManyUsers(ids) 
    let promises = ids.map(id => User.find(id));
    return Promise.all(promises);


findManyUsers(['A', 'B', 'C']).then(result => console.log(result));

【讨论】:

【参考方案2】:

我建议你看看async,它是一个很棒的库,可以处理这类事情等等,我真的认为你应该习惯于实现它。

我会使用以下方法解决您的问题

const async = require('async')

let notuser = [];

async.forEach(users, (user, callback)=>
     User.find(, (err, results) => 
          if (err) callback(err)

          if(results.length) 
               notUser.push(x)
               callback(null)
          
     )
, (err) => 
     err ? throw err : return(notuser)
)

但是,如果您不想使用 3rd 方库,最好使用 promise.all 并等待它完成。

编辑:记得安装async 使用npmyarn 类似于yarn add async 的东西——npm install async

【讨论】:

err ? throw err : return(notuser) 在异步回调中真的没有意义 我只是按照他的逻辑,他想在有错误的时候抛出一个错误。我的示例背后的目标是向用户展示 async【参考方案3】:

我使用@danh 解决方案作为在我的场景中进行修复的基础(因此值得称赞),但我认为我的代码可能与其他人相关,希望在没有异步的情况下使用标准猫鼬。我想获取某个状态的报告数量的摘要,并返回每个报告的最后 5 个,并合并为一个响应。

const  Report  = require('../../models/report');
const Workspace = require('../../models/workspace');

// GET request to return page of items from users report
module.exports = (req, res, next) => 
  const workspaceId = req.params.workspaceId || req.workspaceId;
  let summary = [];

  // returns a mongoose like promise
  function addStatusSummary(status) 
    let totalItems;
    let $regex = `^$status$`;
    let query = 
      $and: [ workspace: workspaceId ,  status:  $regex, $options: 'i'  ],
    ;

    return Report.find(query)
      .countDocuments()
      .then((numberOfItems) => 
        totalItems = numberOfItems;
        return Report.find(query)
          .sort( updatedAt: -1 )
          .skip(0)
          .limit(5);
      )
      .then((reports) => 
        const items = reports.map((r) => r.displayForMember());
        summary.push(
          status,
          items,
          totalItems,
        );
      )
      .catch((err) => 
        if (!err.statusCode) 
          err.statusCode = 500;
        
        next(err);
      );
  

  Workspace.findById(workspaceId)
    .then((workspace) => 
      let promises = workspace.custom.statusList.map((status) =>
        addStatusSummary(status)
      );
      return Promise.all(promises);
    )
    .then(() => 
      res.status(200).json(
        summary,
      );
    )
    .catch((err) => 
      if (!err.statusCode) 
        err.statusCode = 500;
      
      next(err);
    );
;

【讨论】:

以上是关于带有多个猫鼬查找的foreach循环后的javascript承诺的主要内容,如果未能解决你的问题,请参考以下文章

具有多个和可选字段的猫鼬查找

从猫鼬的多个集合中获取数据?

带有两个数组的Java foreach循环[重复]

PHP foreach循环中的多个索引变量

Java学习集合

Java学习集合