问题引入:今天在 Gulp 构建任务中出现一个 html 解析错误,但是并没有报错,也没有中断 gulp 构建任务的执行,而是出现 UnhandledPromiseRejectionWarning 的警告,所以会误以为构建成功,这篇文章将对此进行探究并解决该问题。

1

2

3

4

5

(node:24866) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error in plugin 'gulp-posthtml'

Message:

Parse Error: <img id="titleIcon" class$="{{getStypeType_(info.stype)}}" src$="{{getTitleIcon_(in

...

(node:24866) [DEP0018] 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.

关于 Unhandled Rejection

一个 Promise 是一个异步操作的状态机,其可能处于这三种状态之一

  • pending:异步操作还在执行中

  • fulfilled:异步操作已经完成

  • rejected:异步操作执行失败

Node.js 6.6.0 added a sporadically useful bug/feature: logging unhandled promise rejections to the console by default.

在 Node.js 6.6.0 中增加了一个特性:对 Promise 中未处理的 rejection 默认会输出 UnhandledPromiseRejectionWarning 提示

例如:test.js 中有如下代码:

1

2

3

new Promise((resolve, reject) => {

setTimeout(() => reject('woops'), 500);

});

node test.js 执行:

1

2

(node:47122) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): error

(node:47122) [DEP0018] 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

另一种情况是直接在 Promise 中抛出异常:

1

new Promise(() => { throw new Error('exception!'); });

执行后也会有 UnhandledPromiseRejectionWarning 的警告:

1

2

(node:47657) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: exception!

(node:47657) [DEP0018] 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.

Promise API 中有 .catch() 这个方法,可以用来处理捕捉 rejection 进行处理

1

2

3

4

5

6

7

8

new Promise((resolve, reject) => {

setTimeout(() => reject('error'), 500);

})

.catch(error => console.log('caught', error))

new Promise(() => { throw new Error('exception!'); })

.catch(error => console.log('caught', error.message))

但是注意:

1

2

new Promise((_, reject) => reject(new Error('woops')))

.catch(error => { console.log('caught', err.message); });

这个例子中虽然用 .catch() 捕捉处理了 Promise 中的 rejection;但是注意在 err.message 中的 err 是未定义的,代码执行时会抛出错误,由于没有后续的处理,所以也会输出 UnhandledPromiseRejectionWarning 的警告

1

2

(node:47918) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): ReferenceError: err is not defined

(node:47918) [DEP0018] 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.

所以稍不注意就会引起 Promise 中的 unhandled rejections ?

unhandledRejection 事件

在 node process 中有一个 unhandledRejection 事件,当没有对 Promise 的 rejection 进行处理就会抛出这个事件(这只对原生 Promise 有效)

The unhandledrejection event is fired when a JavaScript Promise is rejected but there is no rejection handler to deal with the rejection.

1

2

3

4

5

6

7

process.on('unhandledRejection', error => {

// Will print "unhandledRejection err is not defined"

console.log('unhandledRejection', error.message);

});

new Promise((_, reject) => reject(new Error('woops')))

.catch(error => { console.log('caught', err.message); });

此时执行后,就没有 UnhandledPromiseRejectionWarning 的警告输出了,只输出:unhandledRejection err is not defined

如果我们不想监听 unhandledRejection 事件,也不想看到 UnhandledPromiseRejectionWarning 的警告输出,怎么办呢?

1

2

new Promise((_, reject) => reject(new Error('woops')))

.catch(new Function());

我们可以在 .catch() 中传入一个空函数,假装对 rejection 进行了处理,这样也没有触发 unhandledRejection 事件

Async/Await

关于 Async/Await,可以参考文章:ES7 中的 async await,在这篇文章中详细介绍了 Async/Await 并且和 Promise 进行了对比,Async/Await 在处理异步操作上的优势更明显。

1

2

3

4

5

6

7

8

9

10

11

12

13

async function test() {

// No unhandled rejection!

await Promise.reject(new Error('test'));

}

test();

// 输出:

// (node:54358) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: test

// (node:54358) [DEP0018] 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.

test().catch(error => console.log(error.message));

// 输出:

// test

async 异步函数返回的是 Promise,所以执行异步函数后,统一需要用 .catch() 对可能出现的 rejection 进行捕捉处理,否则统一也是会出现 UnhandledPromiseRejectionWarning 的警告

解决问题

最后解决一下文章开头的问题:构建任务中 html 解析错误,出现了一个 Unhandled Rejection,所以我们可以添加一个 unhandledRejection 事件监听,直接退出:

1

2

3

4

process.on('unhandledRejection', error => {

console.error('unhandledRejection', error);

process.exit(1) // To exit with a 'failure' code

});

参考链接

Unhandled Promise Rejections in Node.js

#Promise

NodeJS中的异步编程经验相关推荐

  1. 深入理解nodejs中的异步编程

    文章目录 简介 同步异步和阻塞非阻塞 javascript中的回调 回调函数的错误处理 回调地狱 ES6中的Promise 什么是Promise Promise的特点 Promise的优点 Promi ...

  2. nodeJS中的异步编程

    nodejs 不是单线程 在博客项目中关于异步问题: 1.当用户添加一条博客时 需要通过post方式向服务器发送数据 后台获取用户以post方式拿到传送过来的数据 然后存入数据库: 上面的代码:创建一 ...

  3. 了解和使用DotNetCore和Blazor中的异步编程

    目录 介绍 您对异步编程了解什么? 那么,什么是异步编程? 我们什么时候应该使用它? 任务.线程.计划.上下文 到底是怎么回事? Asnyc编码模式 命名约定 异步任务模式 任务模式 事件模式 阻塞与 ...

  4. 一文说通C#中的异步编程补遗

    前文写了关于C#中的异步编程.后台有无数人在讨论,很多人把异步和多线程混了. 文章在这儿:一文说通C#中的异步编程 所以,本文从体系的角度,再写一下这个异步编程.   一.C#中的异步编程演变 1. ...

  5. 一文说通C#中的异步编程

    天天写,不一定就明白. 又及,前两天看了一个关于同步方法中调用异步方法的文章,里面有些概念不太正确,所以整理了这个文章.   一.同步和异步. 先说同步. 同步概念大家都很熟悉.在异步概念出来之前,我 ...

  6. 【转】.Net中的异步编程总结

    一直以来很想梳理下我在开发过程中使用异步编程的心得和体会,但是由于我是APM异步编程模式的死忠,当TAP模式和TPL模式出现的时候我并未真正的去接纳这两种模式,所以导致我一直没有花太多心思去整理这两部 ...

  7. .NET中的异步编程——常见的错误和最佳实践

    目录 背景 async void 没有线程 Foreach和属性 始终异步 在这篇文章中,我们将通过使用异步编程的一些最常见的错误来给你们一些参考. 背景 在之前的文章中,我们开始分析.NET世界中的 ...

  8. Linux中C语言编程经验总结

    ​ 修改记录 版本号 日期 更改理由 V1.0 2022-03-15 MD化 V1.01 2023-02-18 0和-1同时作为非法值的建议 总则 仅总结一些常用且实用的编程规范和技巧,且避免记忆负担 ...

  9. C#中的异步编程(Async)

    文章目录 C#中的异步编程(Async) 前言 示例代码 C#中的异步编程(Async) 前言 所谓的异步,就是指代码在运行的过程中,不会发生阻塞,例如我们玩游戏的时候,游戏在下载资源或者在加载本地资 ...

最新文章

  1. LVM使用手册简化命令
  2. Python语法中的模糊语义,你知道吗?
  3. c# 读取写入excel单元格基本操作
  4. Linux 系统目录
  5. 35.使用拦截器实现权限验证
  6. Android - Glide4.4.0使用
  7. 在Ubuntu 16.04.3 LTS 和 Windows 下安装 Go 环境
  8. 想精通正则表达式 这几个正则表达式学习资料及工具你必须有!
  9. 深度学习实践指南(三)—— 参数(超参)及数据集的处理
  10. 任务 F :工时统计
  11. oracle日期型to_char,Oracle 日期函数to_char
  12. vue项目退出登录清除 store 数据
  13. 3种内网穿透方式连接家用宽带服务器
  14. cad导入新的线型、填充图案、字体压缩包
  15. ubuntu16.04环境Kdevelop安装和汉化
  16. python做三维图片挑战眼力_挑战眼力!三维立体图片你能看出几个
  17. 如何自己租GPU服务器(阿里云)跑pytorch代码
  18. [Unity3D]Unity3D游戏开发之仿仙剑奇侠传角色控制效果
  19. 【时序】MQ-RNN 概率预测模型论文笔记
  20. python计算圆的体积_[宜配屋]听图阁

热门文章

  1. [scala基础]--Option/Some/None
  2. python分苹果问题_分苹果问题的C++和Python实现
  3. 脚本下载安装及其使用,Tampermonkey脚本网站使用(Tampermonkey真是宝藏,偷偷看)
  4. 怎样将「插件化」接入到项目之中?
  5. 应用动态规划思想解决实际问题
  6. 职中选什么专业好_职高毕业,迷茫中,选什么专业和学校好
  7. 模仿新浪微博雷达搜索动画效果
  8. 漫步微积分二十——微分和切线逼近
  9. 2万字深度解读麦克斯韦方程组,最美的方程,你也能懂她的美
  10. 成都东软学院2016年ACM冬季校赛正式赛 - 题解