使用猫鼬的正确方法是什么?

时间:2017-11-02 22:50:35

标签: javascript node.js mongodb mongoose promise

我是Promises的新人,在两天内已经看到了至少五种方法。

有些方法是旧版本,有些则专注于其他语言,所以我决定问今天应该使用什么。

我是这样做的,错误的是'和' doc'参数:

Proposals.findById({ ...body, user }, (err, doc) => 
    Advertisements.findOneAndUpdate(
        {_id:  body.advertisement}, {$push: {proposals: doc._id}}
    )
)
.then((Proposals) => Proposals.view())
.then(success(res, 201))
.catch(next)

而且:

Proposals.create({ ...body, user })
.then((Proposals) => {
    Advertisements.findOneAndUpdate(
        {_id:  body.advertisement}, {$push: {proposals: Proposals._id}}
    )
    .catch(Advertisements)

    return Proposals.view()
}) 
.then(success(res, 201))
.catch(next)

没有" catch"并且"返回"它不起作用,但我不知道为什么。 :X

答案 Using Promises in Mongoose Routes 看起来很漂亮,但我无法在上面的代码中重现。

return findUser(userId)
  .then((user) => findReceipt(user.bookName))
  .then((receipt) => res.status(200).json(receipt))
  .catch((err) => res.status(500).json(null))

这些代码中的任何一个更正确吗? 你能帮我解决第二个代码吗?

谢谢。

3 个答案:

答案 0 :(得分:1)

让我详细说明第一个代码块的语法:

Proposals.findById({ ...body, user }, (err, doc) => {
  return Advertisements.findOneAndUpdate(
    {_id:  body.advertisement}, {$push: {proposals: doc._id}}
  );
})
.then((Proposals) => { return Proposals.view() })
.then(success(res, 201))
.catch(next)

在ES6语法中,此函数:

() => ('test');

等于

() => { return 'test' };

所以我认为你的主要问题是因为一开始并不完全理解ES6语法。

Promises

时,您应该遵循这些最佳做法
  1. 避免在catch
  2. 中嵌套Promises
  3. Promises返回并在then
  4. 中使用它们

    希望它有所帮助。

答案 1 :(得分:0)

示例代码不等待或使用更新结果。

在promises中return承诺并使用.then等待异步操作。然后,您可以根据需要检查结果:

Proposals.create({ ...body, user })
.then((proposal) => {
    return Advertisements.findOneAndUpdate(
        {_id:  body.advertisement}, {$push: {proposals: proposal._id}}
    )
}) 
.then((update) => {
  if (!update) throw new Error(`Could not find advertisement for "${user}"`)
  success(res, 201))
})
.catch(next)

使用await等待承诺解析的等效ES2017代码,这有助于推理上述Promise .then代码流的工作原理。

async function handler(){
  try {
    let proposal = await Proposals.create({ ...body, user })
    let update = await Advertisements.findOneAndUpdate(
      {_id:  body.advertisement}, {$push: {proposals: proposal._id}}
    )
    if (!update) throw new Error(`Could not find advertisement for "${user}"`)
    success(res, 201)
  }
  catch (err) {
    next(err)
  }
}

答案 2 :(得分:0)

处理Mongoose中的承诺有多种方法。您决定实施它的确切方式取决于个人偏好,但您需要确保您的执行顺序符合预期。在你的第一个例子中,你将回调与promises混合,我个人认为这不是最优的。第三个例子更清晰,因为它是通过then调用传递下来的一系列承诺。

需要注意的重要一点是,如果您想在then次调用中运行异步代码,则需要确保返回在适当时刻解决的Promise。在第二个示例中,您可能在findOneAndUpdate调用完成执行之前返回。您可以通过多种方式避免这种情况。一种选择是将第二个调用包装在Promise内。我通过混合你的第二和第三个例子的部分并假设proposal.view()的返回值不是异步来给你一个想法。为清晰起见,我使用了明确的return语句。

Proposals.create({ ...body, user })
  .then((proposal) => {
    // call returns a new promise
    return new Promise((resolve, reject) => {
      // make second async call to database
      Advertisements.findOneAndUpdate(
        { _id:  body.advertisement }, 
        { $push: { proposals: proposal._id } },
      )
      .then(() => {
        // promise resolves here and passes return
        // value of proposal.view() to next `then`
        return resolve(proposal.view())
      });
    });
  })
  // consume the value from proposal.view() and send it in response
  .then(proposal => res.status(200).json(proposal))
  .catch(next)

这意味着proposal.view()的返回值只会在then调用完成后传递到下一个findOneAndUpdate