带有多个猫鼬的foreach循环后的JavaScript许诺

时间:2018-12-22 14:47:40

标签: javascript node.js mongoose promise

我正在尝试对一些数据库调用进行循环,一旦它们全部完成都会发送结果。 -使用promise,但是如果我在回调后有我的promise,它将起作用。

  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)

})

我该如何处理?

3 个答案:

答案 0 :(得分:1)

下面是一个名为findManyUsers的函数,它可以满足您的需求。 Mongo find将向您返回一个承诺,因此只需循环收集这些承诺并与Promise.all()一起运行它们即可。因此,您可以看到它的运行情况,我添加了一个模拟用户类,其中包含一个返回承诺的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));

答案 1 :(得分:0)

我建议您看看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)
})

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

编辑:记住使用asyncnpm类似于yarn-yarn add async

安装npm install async >

答案 2 :(得分:0)

我使用@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);
    });
};