Node.js UnhandledPromiseRejectionWarning 即使在捕获它之后

2024-03-23

我正在使用 Node 7.2.1 和新版本异步/等待特征。我还将 Native ES6 Promises 与 mongoose 一起使用,如下所示 -

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

我的代码流程是这样的 -

async function getFollowers(){
    try {
        const followers = await User.getFollowersFromMongo(req.params.userId);
        res.send(followers);
    } catch (err) {
        winston.error('Printing Error = ', err);
        res.status(400).send({success: false, error: err});
    }
}

UserSchema.statics.getFollowersFromMongo = async(userId) => {
    try {
        let aggregateQuery = []; //some syntactical error in mongo query to produce exception

        const followers = await User.aggregate(aggregateQuery);
        return followers.map(follower => follower.followerData);
    }
    catch (err) {
        return Promise.reject(err);
    }
};

这段代码工作得非常好。当产生一些错误时就会出现问题。所以我特意修改了我的mongoose查询以便MongoDB会抛出一个错误。

现在,MongoDB 正如预期的那样抛出一个错误,该错误被我的代码完美捕获,并以 400 错误代码返回给客户端。

问题是,即使错误(故意的)已被我发现,Node.js仍然给我这个警告 -

error:  Printing Error = MongoError: path option to $unwind stage should be prefixed with a '$': followerData
at Function.MongoError.create (/home/node_modules/mongodb-core/lib/error.js:31:11)
at /home/node_modules/mongodb-core/lib/connection/pool.js:483:72
at authenticateStragglers (/home/node_modules/mongodb-core/lib/connection/pool.js:429:16)
at Connection.messageHandler (/home/node_modules/mongodb-core/lib/connection/pool.js:463:5)
at Socket.<anonymous> (/home/node_modules/mongodb-core/lib/connection/connection.js:317:22)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:551:20)

GET /user/385/followers 400 39.868 ms - 263

(node:10158) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: path option to $unwind stage should be prefixed with a '$': followerData
(node:10158) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

可以看出,我的请求已返回 400 状态,并且我的错误日志也已从初始方法的 catch 块中打印出来,但是Node.js仍然说错误消息未处理。

为什么在发现同样的错误后仍然这么说?

Update -感谢@dvlsg和@Bergi,该bug已在4.7.5版本中修复


猫鼬聚合与 async/await 的配合方式肯定有些奇怪。对我来说,这似乎是一个错误。如果是的话,绝对应该报告给 mongoose。

值得庆幸的是,有一个简单的解决方法:

const followers = await User.aggregate(aggregateQuery).exec();

添加显式.exec()允许我按预期捕获聚合管道错误。


我认为这里增加混乱的根本问题是还有一个额外的问题Promise漂浮在周围,被拒绝且未被处理。因为从技术上来说,你are正确处理这里预期的拒绝。不然你就看不到那个Printing error = ...正在记录。

这就是我相信正在发生的事情——

  • You await User.aggregate()
  • Aggregate#then()被调用通过await与...一起工作thenables(我认为)
  • Aggregate#exec() is called internally by Aggregate#then()
    • 注意提供回调 https://github.com/Automattic/mongoose/blob/09a1d72178eb9cb0873e457787e10e235cead07a/lib/aggregate.js#L609 to exec()
  • A new Promise inside Aggregate#exec() is created https://github.com/Automattic/mongoose/blob/09a1d72178eb9cb0873e457787e10e235cead07a/lib/aggregate.js#L562, and will be rejected https://github.com/Automattic/mongoose/blob/09a1d72178eb9cb0873e457787e10e235cead07a/lib/aggregate.js#L419
    • This是未处理的Promise, 我相信。
  • 由于提供了回调Aggregate#exec() from Aggregate#then(), the Error inside Aggregate#exec()提供给回调 https://github.com/Automattic/mongoose/blob/09a1d72178eb9cb0873e457787e10e235cead07a/lib/aggregate.js#L565-L567
  • Inside the callback in Aggregate#then(), a newly created https://github.com/Automattic/mongoose/blob/09a1d72178eb9cb0873e457787e10e235cead07a/lib/aggregate.js#L608 Promise is rejected
    • 我相信这一点Promise按预期处理,因为它是从返回Aggregate#then()

我想我可以通过评论来证实我的怀疑这条线 https://github.com/Automattic/mongoose/blob/09a1d72178eb9cb0873e457787e10e235cead07a/lib/aggregate.js#L568在猫鼬中Aggregate定义。这将防止未处理的拒绝处理程序被击中。顺便说一句,我并不是建议这样做。这只是额外的证据,不是解决方案,因为现在我只有一个未拒绝的Promise漂浮在周围。


这是一种在自包含的代码中重现未捕获拒绝的最小方法,可以使用node --harmony-async-await(在节点上测试v7.2.1)

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/temp');

const userSchema = new mongoose.Schema({
  name: 'string'
});

const User = mongoose.model('User', userSchema);

async function run() {
  try {
    await User.aggregate([]);
  }
  catch (err) {
    console.log('caught expected error:', err);
  }
}

run();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node.js UnhandledPromiseRejectionWarning 即使在捕获它之后 的相关文章

  • 无法读取未定义错误的属性“匹配”

    我试图在 React JS 前端显示一些文本来代替个人资料图像 当它不可用时 基本上 我将当前客户名称传递给一个函数 该函数提取名称中所有单词的第一个字符 我能够仅显示名称 但是当我执行函数调用时 出现 无法读取未定义的属性 匹配 错误 并
  • 如何隐藏 URL 中的 ID

    我以前在 Stack Overflow 上见过这类问题 但没有一个真正有帮助 我也用谷歌搜索过 但没有骰子 我想知道如果用户单击选项卡本身是否可以隐藏 URL 中的 ID 这是网页 www planet nu dev new experia
  • webpack 加载器并包含

    我是 webpack 的新手 我正在尝试了解加载器及其属性 例如测试 加载器 包含等 这是我在 google 中找到的 webpack config js 的示例片段 module loaders test js loader babel
  • 如何在 Angular 模板中嵌入 GitHub gist?

    角度忽略script其模板中包含标签 但加载 GitHub gist 需要它们 执行此操作的最佳做 法是什么 使用iframe 创造script动态标记 或者是其他东西 一种方法是创建一个iframe with script里面并在你希望你
  • Javascript:更改浏览器后退按钮的功能

    有没有办法让用户的浏览器上的后退按钮调用 JavaScript 函数而不是返回页面 您无法覆盖这样的行为 如果用户通过链接访问您的页面 则单击 后退 将使他们再次离开该页面 但是 您可以使页面上的 JavaScript 操作将条目添加到历史
  • ES6 生成器——它们真的是 async/await 的替代品吗?

    评论区的帖子之一this http blogs msdn com b typescript archive 2014 10 22 typescript and the road to 2 0 aspx打字稿博客文章说 如果我必须等到 2 0
  • 如何在 MongoDB 中创建 Mongoose 模型而不创建集合?

    我只想有一个versioneditemsMongoDB 中的集合 但我需要注册VersionedItem模型和ItemPatch模型 因为我需要创建ItemPatches 填充 aVersionedItem 不会有单独的ItemPatch文
  • 如何用方向键移动div

    我想使用 jQuery 用箭头键移动 div 所以右 左 下 上 找到了我想要完成的演示here http atomicrobotdesign com blog htmlcss move objects around the canvas
  • Javascript 3d 绘图实用程序? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有什么好的 javascript 3d 绘图实用程序吗 我知道每个网站都推荐过画布 3d 图
  • C# 异步任务比同步慢

    你知道为什么同步斐波那契方法比异步 等待更快并且比异步任务更快吗 我在每个项目方法上都使用了异步 所以主要是这是一个非常糟糕的方法 Code static int FibonacciSync int number if number 0 r
  • 在 Jest 测试中设置时刻时区

    我有 util 函数 它以特定的日期格式解析给定的日期 即 2019 01 28 然后使用momentJS检索当天的开始并将其转换为 ISO 日期格式 dates js import moment from moment export co
  • 如何使用jsPDF设置图像以适合页面宽度?

    有什么办法可以解决这个问题吗 我尝试以毫米为单位设置宽度和高度 如何将其设置为全角 您可以获取 PDF 文档的宽度和高度 如下所示 var doc new jsPDF p mm a4 var width doc internal pageS
  • Javascript 警报/消息框中的欧元符号或其他实体

    有谁知道我如何在 javascript 警报窗口中显示欧元或其他 html 实体 alert u20AC HTML 实体字符查找 http leftlogic com lounge articles entity lookup
  • FluentAssertions ShouldNotThrow 无法识别异步方法/Func

    我正在尝试检查异步方法是否抛出具体异常 为此 我使用 MSTEST 和 FluentAssertions 2 0 1 我已经检查过这个关于 Codeplex 的讨论 http fluentassertions codeplex com wo
  • 原型链、构造函数、继承

    我正在玩 javascript 原型 我是新手 所以我有一个小问题 我正在用这个article http mckoss com jscript object htm作为指导 我已经定义了产品和书籍 目的是什么Book prototype c
  • 图像未显示在从 HTML 创建的 PDF 上

    我想动态创建 PDF 这意味着我将从 Google Drive 获取文件 然后将它们放入 HTML 代码中 并尝试从中创建 PDF 一切工作正常 除了图像没有显示 我现在正在做的是 从 HTML 字符串创建 HtmlOutput 获取该 H
  • 更改哈希值而不触发 hashchange 事件

    我使用哈希来动态加载内容 为了使后退按钮正常工作 我正在捕获哈希更改 然而 有时我需要更改哈希值而不触发哈希更改函数 例如 当页面重定向到服务器端时 我需要在内容返回后更新哈希值 我想出的最佳解决方案是取消绑定 hashchange 事件
  • 如何使用 Typescript 设置 Material-UI for React?

    我在将 Material UI 添加到我的 React 项目中时遇到了一些问题 该项目是用 Typescript 编程的 根据教程 我首先添加react tab event plugin import injectTapEventPlugi
  • 如何在画布中旋转图表同时保持数字垂直?

    我正在尝试围绕其中心旋转画布中的图表 同时保持字母直立 我正在尝试使用 ctx rotate 但它使用画布的左侧作为中心来旋转整个图表 以下链接提供了视觉效果 我希望它看起来像绿色 而不是红色 就像我的代码当前所做的那样 视觉解释 http
  • Javascript 最佳实践,为什么使用逗号来链接函数/变量声明?

    我一直在为 jQuery jQueryLog 开发一个插件 以允许调试链选择器和返回值 如果你想检查一下 你可以这样做here http www jquerylog com 这已经是第二个版本了 第一个版本实际上是经过编辑的 jQuery

随机推荐