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

 

开胃汤

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

自然发生的错误:

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

变量y未定义,所以运行时产生了错误,这就是自然发生的错误,我们没有做异常处理,即try catch

主动抛出的错误:

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

 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'

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

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

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

 

正餐

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

书上有这么一个示例:

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

那我们就手动实践一下吧

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

代码:

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

 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 })

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

运行截图:

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

 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 })

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

 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 })

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

Android培训,安卓培训,手机开发培训,移动开发培训,云培训培训

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

 

结语

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

http://www.cnblogs.com/sampapa/p/6979260.html