在 Mongoose 路由中使用 Promise

Posted

技术标签:

【中文标题】在 Mongoose 路由中使用 Promise【英文标题】:Using Promises in Mongoose Routes 【发布时间】:2016-12-16 02:23:08 【问题描述】:

我理解 javascript 中的 Promise 或至少我认为我理解(​​如果我错了,请纠正我)。

创建承诺:

var promise = new Promise(function(resolve, reject)
  // do something async here

  if(itWorked)

    resolve();

  else 

    reject();
  

);

使用承诺:

promise.then(function(result)

,function(err)

);

我有一个基于 MEAN Stack 的应用程序,我的一些 mongoose 路由正在成为回调地狱。我想摆脱猫鼬路由中的回调并使用 Promises 处理它们。但我似乎无法弄清楚该怎么做。

例如:

app.get('/users', function(req, res)

  User.findOne(_id, function(err, user)
      if(err)
         console.log(err)
      else if(user)

         Receipt.findOne(user.bookName, function(err, book)
           if(err)
            console.log(err)

           else if(book)
             // again do something here
            
       )
     
   )
);

在上面的示例中,您可以看到代码变得越来越难以阅读和维护。我如何在这里使用 Promises 来改进我的代码?

【问题讨论】:

【参考方案1】:

好的,首先您使用的是mongoose 对吗?

User 是您的猫鼬模型,它响应诸如findOne(query)findOneAndUpdate(query, update, opts) 等方法。

调用这些方法中的任何一个后,调用方法exec(),它会返回一个查询。

查询并不完全是 Promise,您需要指定 Mongo 将使用哪些 Promise。在这里我建议使用原生的,所以在你的项目中添加这一行:

 const mongoose = require('mongoose')
 mongoose.Promise = Promise

现在,这条指令正在返回一个 Promise,很好!

User.findOne(q).exec()

您现在可以使用您的逻辑创建一个 Promise 链,例如:

 return User
     .findOne(_id)
     .exec()
     .then((user) => 
       return Receipt
         .findOne( bookName: user.bookName )
         .exec()
       )
     .then((receipt) => 
            // example
            return res.status(200).json(receipt)
         ))
     )

提示:我建议创建辅助方法以使代码更加简洁:

/** @return Promise */
function findUser(id) 
  return User.findOne(id).exec()


/** @return Promise */
function findReceipt(bookName) 
  return Receipt.findOne( bookName ).exec()


// example
function f(req, res) 
  const userId = req.get('id')

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


// register your handler
app.get('/book', f)

【讨论】:

非常感谢您的回答。我有几个问题要澄清一些概念。在mongoose.Promise = Promise 行中,您是否将本机 ES6 承诺库插入到猫鼬中?当_findUser 承诺返回时,then 函数会运行吗?我猜returning a promise这个词的意思是_findUser函数是否有resolvedrejected。我说的对吗? 没错,mongoose.Promise = Promise 告诉 mongoose 使用原生 ES6 承诺;链接承诺:_findUser() 是一项繁重的任务,总有一天会返回预期的用户,你解决了user 你可以开始一个新任务(你注意到返回了吗?)_findReceipt()。这也是一项繁重的任务,将返回receipt您已解决receipt 您已准备好返回您的回复。如果这些任务中的 ANY 引发错误,您将执行 catch 语句 非常感谢您的解释。我现在基本明白了。出于某种原因,我发现承诺很难理解。 你会勾选这个答案吗?

以上是关于在 Mongoose 路由中使用 Promise的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 jQuery .ajax() 路由的 .done() 方法没有在我的 NodeJS、Express 和 Mongoose 项目中触发?

在多个文件中使用 Mongoose Schema (mongoose)

如何使用 Mongoose 在 AngularJS 中创建 PUT 函数

基于 GET 参数的 Express/Mongoose REST API 路由

Mongoose/Angular/Node:使用 deleteOne 方法的路由一直说对象已删除,但删除计数为零

在 ejs 模板文件中使用 mongoose 获取数据