符合PromiseA+规范并不表明与浏览器表现一致

引出问题

不处理reject,浏览器会抛异常吗?

考虑下列代码的执行状况git

new Promise(function(resolve, reject) {
    reject('reason')
})
复制代码

不少同窗估计都会去Chrome的控制台输出一下,发现这段代码其实会往外抛一个异常github

可是参考一个经过Promise/A+规范测试的Promise的源码,发现其reject并无往外抛出异常npm

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)
      }
    }
  }
复制代码

参考文章: 剖析Promise内部结构,一步一步实现一个完整的、能经过全部Test case的Promise类(目前大部按照PromiseA+规范实现Promise的文章,代码基本都是这样的,其中这篇讲解比较详细,具备表明性)promise

查阅了一下PromiseA+的规范,其实并无规定reject要向外抛出错误浏览器

各个引擎中的表现

  • Nodejs
    Nodejs和Chrome同样,也是基于v8的JS引擎。因此首先看看再Nodejs下的表现
    函数

  • Edge
    没抛异常,且IE看不到Promise的状态
    测试

  • Firefox
    ui

为何

promise-polyfill库中找到了这样的方法 spa

大意就是,在reject里面会执行Promise._unhandledRejectionFn方法,由用户本身决定怎么处理这个reject的异常。显然大多数浏览器原生Promise的选择是,若是没有catch进行处理,就抛出code

总结

  1. 其实,通常状况下,规范的使用catch就不会有上述问题了。在reject的状况下,只要后面有catch处理,就不会抛出异常。没有catch的状况下,通常会往外抛异常
  2. 在then的回调函数中,若是出现了异常且后面没有catch,仍是会向外抛出异常,因此合理使用catch是很重要的
  3. 最后,并非说讲解Promise实现的文章很差,而是PromiseA+没有明确指出上述状况,因此但愿读者可以了解到浏览器上的表现差别。
相关文章
相关标签/搜索