引出问题
不处理reject,浏览器会抛异常吗?
考虑下列代码的执行情况
new Promise(function(resolve, reject) { reject('reason')})复制代码
很多同学估计都会去Chrome的控制台输出一下,发现这段代码其实会往外抛一个异常
但是参考一个通过Promise/A+规范测试的Promise的源码,发现其reject并没有往外抛出异常
function reject(reason) { if (self.status === 'pending') { // 改变状态 self.status = 'rejected' // 保持值 self.data = reason // 执行回调 for(var i = 0; i < self.onRejectedCallback.length; i++) { self.onRejectedCallback[i](reason) } } }复制代码
参考文章: (目前大部按照PromiseA+规范实现Promise的文章,代码基本都是这样的,其中这篇讲解比较详细,具有代表性)
查阅了一下的规范,其实并没有规定reject要向外抛出错误
各个引擎中的表现
-
Nodejs
Nodejs和Chrome一样,也是基于v8的JS引擎。所以首先看看再Nodejs下的表现 -
Edge
没抛异常,且IE看不到Promise的状态 -
Firefox
为什么
在库中找到了这样的方法
大意就是,在reject里面会执行Promise._unhandledRejectionFn
方法,由用户自己决定怎么处理这个reject的异常。显然大多数浏览器原生Promise的选择是,如果没有catch进行处理,就抛出
总结
- 其实,一般情况下,规范的使用catch就不会有上述问题了。在reject的情况下,只要后面有catch处理,就不会抛出异常。没有catch的情况下,一般会往外抛异常
- 在then的回调函数中,如果出现了异常且后面没有catch,还是会向外抛出异常,所以合理使用catch是很重要的
- 最后,并不是说讲解Promise实现的文章不好,而是PromiseA+没有明确指出上述情况,所以希望读者能够了解到浏览器上的表现差异。