【问题标题】:nodejs Promise.all returns null on some mongoose promisesnodejs Promise.all 在某些 mongoose 承诺上返回 null
【发布时间】:2018-05-11 10:14:31
【问题描述】:

我正在传递一组猫鼬承诺,由于某种原因,有时 customerFindPromise 返回 null,有时它返回请求的对象。我在这里做错了吗

******************** START result0: null result END ********************
 ******************** START result1: { _id: 5a18a637346826574416a588,
doc_fname: 'Bob',
doc_lname: 'Smith',
numOfCases: 1,
__v: 0 } result END ********************
******************** START result2: {"n":1,"ok":1} result END ********************

代码

var customer = {
    doctor_id: 5a18a637346826574416a588,
    cust_fname: 'dfsdf',
    cust_lname: 'sdasd',
    case_type: 'Crowns',
    _id: 5a1cd19438f14164b0087753 
}
test(customerCase);
async function test(customerCase) {

    console.log("******************** customerCaseDelete: "+ customerCase._id +" ********************");
    var _id = customerCase._id;
    var doctor_id = customerCase.doctor_id;
    var query = {_id:_id};

    const customerFindPromise = CustomerCases.findById(_id);
    const customerRemovePromise = CustomerCases.remove(query);
    const doctorUpdatePromise = Doctors.findOneAndUpdate({_id:doctor_id},{'$inc': {'numOfCases': -1}},{new:true});

    await Promise.all([customerFindPromise,doctorUpdatePromise,customerRemovePromise])
      .then((result) => {
        console.log("******************** START result0: "+ result[0] +" result END ********************");
        console.log("******************** START result1: "+ result[1] +" result END ********************");
        console.log("******************** START result2: "+ result[2] +" result END ********************");
        res.json(result);
      }).catch((err) => {
          console.log("******************** START err: "+ err +" err END ********************");
         throw err;
      });
}

【问题讨论】:

  • 您发布的代码无效,特别是var customer的声明
  • 同时查找和删除具有相同 id 的对象显然是典型的竞争条件。

标签: javascript node.js mongodb mongoose promise


【解决方案1】:

您正在运行的函数是异步的,并不总是按顺序运行。 Promise.all 也不会改变 Promise 的执行顺序,它只是等待它们都被解决。

有时CustomerCases.remove 会在CustomerCases.findById 之前执行和解析,所以null 会在文档首先被删除时解析。

在执行下一个查询之前等待promise连续解析,因为您使用的是async/await,添加起来相当简单:

try{
  let find = await CustomerCases.findById(_id)
  console.log(`find: ${find}`)
  let update = await CustomerCases.remove(query)
  console.log(`update: ${update}`)
  let remove = await Doctors.findOneAndUpdate({_id:doctor_id},{'$inc': {'numOfCases': -1}},{new:true})
  console.log(`remove: ${update}`)
  res.json([find, update, remove])
} catch(err) {
  console.error(err)
  throw err // next(err)?
}

如果您需要串行执行助手,请尝试 bluebirds Promise.each

【讨论】:

  • Promise 不会“运行”,Promise.all 中也没有“执行”,所以也没有顺序。
  • @Bergi 更好的术语?
  • 谢谢@Matt,我认为通过将 await 添加到 Promise 中它不会同时执行所有 Promise。是否可以添加 Promise.all,对于这种情况是否有必要。
  • @Matt 谢谢你的解决方案,如果其中一个猫鼬函数失败了,是否可以恢复已执行的函数
  • Mongo 不做开箱即用的交易。您需要根据错误手动回滚所需的数据。
猜你喜欢
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
  • 2018-05-03
  • 2016-11-28
  • 1970-01-01
  • 2019-10-21
相关资源
最近更新 更多