将 Async/await 与 mongoose 一起使用

Posted

技术标签:

【中文标题】将 Async/await 与 mongoose 一起使用【英文标题】:Using Async/await with mongoose 【发布时间】:2019-04-15 17:03:49 【问题描述】:

我正在学习 Stephen Grinder 的 NodeJS 高级课程,我们在其中测试了 Redis 中的缓存。

当我运行我的应用程序并到达给定的路线时,我遇到了这个错误

DeprecationWarning: Mongoose: mpromise (mongoose 的默认承诺 library) 已弃用,请插入您自己的 Promise 库: http://mongoosejs.com/docs/promises.html

还有一个像这样的

UnhandledPromiseRejectionWarning:未处理的承诺拒绝。这 错误源于在异步函数内部抛出 没有 catch 块,或拒绝未处理的承诺 使用 .catch()。 (拒绝 ID:1)[0](节点:11896)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。在 未来,未处理的承诺拒绝将终止 具有非零退出代码的 Node.js 进程。 [0] 从 MongoDb 提供服务

现在,如前所述,我非常模糊地查看并查看了它,似乎他们的文档没有谈论异步和等待。

这是抛出错误的api路由

  app.get('/api/blogs', requireLogin, async (req, res) => 
    const redis = require('redis')
    const redisURL = 'redis://127.0.0.1:6379';
    const  client = redis.createClient(redisURL);
    const util = require('util')
    client.get = util.promisify(client.get)
    const cachedBlog = await client.get(req.user.id) 
    if (cachedBlog)  return res.send(JSON.parse(cachedBlogs))
    console.log("serving from MongoDb")
    const blogs = await Blog.find(_user: req.user.id)
    client.set(req.user.id, JSON.parse(blogs))
    res.send(blogs);
  );

这里要具体说明这一行

 const blogs = await Blog.find(_user: req.user.id)

在哪里

const Blog = mongoose.model('Blog');

注意:为了简单地解释缓存,Stephen Grinder 特意将它设置在根目录中。

[问题:] 谁能告诉我如何使用 async/await(就像我目前在路由中所做的那样)而不会引发任何错误?

【问题讨论】:

不知道为什么这里的答案被删除或者为什么这里有这么多来回的评论,但是 "warning" (这不是一个“错误”)来了由于缺少mongoose.Promise = global.Promise 或类似设置。 文档参考位于问题 Plugging in your own Promises Library 中参考页面的下方,虽然文档“示例”使用 Bluebird,但它不是该库独有的,而是任何 Promise 实现。 另一方面,UnhandledPromiseRejectionWarning: 是指您对async/await 的使用,而没有专门解决try..catch 块内的Promise。因此 WARNING (再次,不是“错误”)。但是,由于您实际上并未在问题的上下文中包含该代码,因此我们无法“明确”告诉您在那里更正什么,而只能是“通用”的回复。我建议google.com/… 获取无数有用的材料,其中包括错误以及如何纠正的示例。 @NeilLunn 指的是这个:***.com/questions/51862570/…我们在使用bluebird的时候不需要使用mongoose.Promise = global.Promise吗?它不再需要?此外,最初我使用的是 Stephen Grinder Advance NodeJs 样板github.com/StephenGrider/AdvancedNodeStarter,上面的代码来自他的博客路线 (github.com/StephenGrider/AdvancedNodeStarter/blob/master/routes/…)(您不会在该路线中看到 redis 部分) 请再次阅读所有内容和链接的参考资料。这与“蓝鸟”或任何其他不正确的答案无关。同样,“警告”不是“错误”。 【参考方案1】:

这里有两个问题。

1: 你没有为 Mongoose 设置 Promise。所以设置它。

mongoose.Promise = global.Promise

2:当您使用 async/await 时,您需要将代码包装在 try/catch 块中。

try  

   // your code

 catch(e) 

  console.log(e);


在你的情况下,代码应该是这样的。

app.get('/api/blogs', requireLogin, async (req, res) => 
   try 
      const redis = require('redis')
      const redisURL = 'redis://127.0.0.1:6379';
      const  client = redis.createClient(redisURL);
      const util = require('util')
      client.get = util.promisify(client.get)
      const cachedBlog = await client.get(req.user.id) 
      if (cachedBlog)  return res.send(JSON.parse(cachedBlogs))
      console.log("serving from MongoDb")
      const blogs = await Blog.find(_user: req.user.id)
      client.set(req.user.id, JSON.parse(blogs))
      res.send(blogs);
   catch(e) 
      console.log(e);
  
);

【讨论】:

在调用 Mongoose "Blog.find()" 函数后你不应该使用 .exec() 来执行它吗?我是异步新手,有点困惑@AbhishekSingh

以上是关于将 Async/await 与 mongoose 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

ModeMongoose 的 Async/Await 与 Mongoose Deep Populate Chain

如何在 mongoose 中使用 async/await

使用Async / await和mongoose

在 express (async/await) 中使用一个 mongoose 查询的输出作为另一个查询的输入

[Node] Catch error for async await

async/await 在全局范围内显示数据