你是否也在学习ES6 Promise时遇到过这个问题?

背景

周末闲来无事,随便翻看了一下阮一峰老师的《ES6 标准入门》第2版,ps:以前在阮一峰老师的官网看过电子版,感受干货满满,因此就买了纸质版;当看到第16章第4节 'Promise.prototype.catch()'时,遇到了一个小困惑,下面咱们来一块儿看一下es6

 

开胃汤

首先,Promise.prototype.catch方法是用来'捕获Promise回调函数中天然发生或主动抛出的错误',何为天然发生?何为主动抛出?ajax

天然发生的错误:promise

1 function a() {
2   var x = 1;
3   console.log(x+y) 
4 }
5 
6 a() // 'ReferenceError: y is not defined'

变量y未定义,因此运行时产生了错误,这就是天然发生的错误,咱们没有作异常处理,即try catch浏览器

主动抛出的错误:异步

 1 function a() {
 2   var x = 1;
 3   try{
 4     console.log(x+y)
 5   }catch(err){
 6     console.log(err)
 7   }  
 8 }
 9 
10 a() // 'ReferenceError: y is not defined'

意识到可能会有异常出现,咱们就用try catch处理,那咱们如何区分一个错误是否被捕获到了呢?很简单,就是看浏览器控制台的日志:函数

未捕获到的错误日志是红色的学习

捕获到的错误日志是黑色的this

 

正餐

上面已经说了Promise.prototype.catch的做用,以及错误的相关知识,那么我究竟遇到了什么问题呢?我们继续往下看spa

书上有这么一个示例:prototype

1 var promise = new Promise(function(resolve, reject){
2   throw new Error('test')
3 })
4 promise.catch(function(error){
5   console.log(error)
6 })
7 // Error: test

那咱们就手动实践一下吧

错误真的被捕获到了,欧耶,perfect!!忽然我又想到Promise不是用来实现异步操做的吗?那咱们就试试ajax吧,而后又意识到没有接口(主要是当时懒得找),那就用SetTimeout代替吧

代码:

 1 new Promise(function (resolve, reject) {
 2 
 3   // 异步方式抛出异常
 4   setTimeout(function () {
 5     throw new Error('出错1')
 6   },2000)
 7 
 8   // 同步方式抛出异常
 9   throw new Error('出错2')
10 }).catch(function (err) {
11   console.log(err)
12 })

运行截图:

纳尼?!错误1没有被捕获?开玩笑呢,让我缓一缓,终于想到了:setTimeout是在Window下执行的,记得不?上面的代码就至关于:

 1 var clock = function () {
 2   setTimeout(function () {
 3     throw new Error('出错1')
 4   })
 5 }
 6 
 7 new Promise(function (resolve, reject) {
 8 
 9   // 异步方式抛出异常
10   clock()
11 
12   // 同步方式抛出异常
13   throw new Error('出错2')
14 }).catch(function (err) {
15   console.log(err)
16 })

当咱们执行一个函数时,归根到底就是把函数体内代码拿到它被调用的地方执行;因此在上上个示例中,在Promise实例中只是启动了setTimeout定时器,以后定时器就和Promise实例彻底没有关系了,由于它被交由Window对象了,因此定时器中抛出的异常没有想咱们想象的被Promise示例捕获,而是未加处理,直接在控制台报错;怎么样?你是否已经理解,若是理解了,咱们再巩固一下,看看下面的代码:

 1 var clock = function () {
 2   setTimeout(function () {
 3     console.log(this === window)
 4     throw new Error('出错1')
 5   })
 6 }
 7 
 8 var func = function () {
 9   throw new Error('出错3')
10 }
11 
12 
13 new Promise(function (resolve, reject) {
14   // 异步方式抛出异常
15   clock()
16 
17   // 执行window.func抛出异常
18   func()
19 
20   // 同步方式抛出异常
21   throw new Error('出错2')
22 }).catch(function (err) {
23   console.log(err)
24 })

这里错误3能不能被catch捕获呢?答案是:Yes

不要被迷惑呦!虽然func是在Promise示例外面定义的,可是它和错误2是抛出方式没两样儿

 

结语

这就是我在学习Promise相关知识时遇到的一个小插曲,我不相信只有我一我的有这个经历,哈哈;关于Promise的其余知识这里不是没有介绍,而是丝毫没有介绍,很差意思,我又调皮了,主要是我以为学习ES6,看阮一峰老师的《ECMAScript 6 入门》就够了,好了,就到这里吧,祝你们周末愉快!!

相关文章
相关标签/搜索