NodeJS异步。在正确形成对象之前发送的标题

我在使用异步调用时遇到了麻烦。这是给我带来麻烦的代码片段

company.find({ managerID: req.session.manager.managerID })
        .exec((err,_companies) => {
            if(err)
                return res.status(500).send({ message: "Uh,oh! Something went wrong." });
            else {
                var data = [];
                var i = 0;
                _companies.forEach(c => {
                    user.find({ companyID: c._id,status: 0})
                    .then(_user => {
                            // console.log(_user);
                            var dummy = {
                                companyID: c._id,companyName: c.companyName,selectedCurrency: c.selectedCurrency,metrics: c.metrics,headAdmin: _user[0].email,headName: _user[0].designer
                            };
                            console.log(dummy);
                            data.push(dummy);
                            console.log(data);
                            i++;
                    }).catch(err => {
                        return res.status(500).send({ message: "Uh,oh! Something went wrong." });
                    });
                });
                if(i == _companies.length)
                    return res.status(200).send({ data: data });
            }
        });

我的数据对象在正确形成之前就已发送。

我试图从.exec切换到.then,希望它可以解决它,甚至试图仅在循环完成后才返回(甚至不返回空数组)。

每当我在console.log("hi")之前调用return res.status(200).send({ data: data})时,它总是在console.log(dummy)之前被打印

等待解决此问题,如果是,我应该如何使用它,因为我对如何使用它不熟悉?

liangpengju20080809 回答:NodeJS异步。在正确形成对象之前发送的标题

Array.prototype.forEach是同步工作的,因此它不必等待user.find()之类的异步操作。因此,i == _companies.length在异步操作完成之前计算为true

如另一个答案中所建议,您可以通过将所有未完成的promise收集到数组中并将其传递给Promise.all()来解决此问题。在您的情况下,看起来可能如下所示:

company.find({ managerID: req.session.manager.managerID })
  .exec((err,_companies) => {
    if (err) {
      return res.status(500).send({ message: "Uh,oh! Something went wrong." });
    }
    const results = _companies.map(c =>
      user.find({ companyID: c._id,status: 0})
        .then(_user => ({
            companyID: c._id,companyName: c.companyName,selectedCurrency: c.selectedCurrency,metrics: c.metrics,headAdmin: _user[0].email,headName: _user[0].designer
        }))
    );
    return Promise.all(results)
      .then(data => res.status(200).send({ data: data }))
      .catch((err) => res.status(500).send({ message: "Uh,oh! Something went wrong." }));
  });
,

那是因为您的forEach在任何循环内都有异步指令。因此,基本上forEach是同步的,但是您在此处插入了promises,并且在forEach中的所有循环都发生之后,您的下一条指令就会执行

如果您使用Bluebird promises(顺序执行)

Promise.mapSeries(_companies,c => /*generate data*/)
.then(res.status(200).send({ data: data }))

或使用Promise.all(并行执行)

Promise.all(_companies.map(c => /*generate data*/)
.then(res.status(200).send({ data: data }))
本文链接:https://www.f2er.com/3094385.html

大家都在问