在 [前面的Promise#then](http://liubin.github.io/promises-book/#ch2-promise.then) 的章节里,我们已经简单地使用了 `Promise#catch` 方法。
这里我们再说一遍,实际上 [Promise#catch](http://liubin.github.io/promises-book/#promise.catch) 只是 `promise.then(undefined, onRejected);` 方法的一个别名而已。 也就是说,这个方法用来注册当promise对象状态变为Rejected时的回调函数。
> 关于如何根据场景使用 [Promise#then](http://liubin.github.io/promises-book/#promise.then) 和 [Promise#catch](http://liubin.github.io/promises-book/#promise.catch) 可以参考 [then or catch?](http://liubin.github.io/promises-book/#then-or-catch) 中介绍的内容。
## 2.5.1\. IE8的问题
[![Build Status](https://box.kancloud.cn/2015-07-20_55ac7319b047a.png)](https://ci.testling.com/azu/promise-catch-error)
上面的这张图,是下面这段代码在使用 [polyfill](https://github.com/jakearchibald/es6-promise) 的情况下在个浏览器上执行的结果。
> polyfill是一个支持在不具备某一功能的浏览器上使用该功能的Library。 这里我们使用的例子则来源于 [jakearchibald/es6-promise](https://github.com/jakearchibald/es6-promise) 。
Promise#catch的运行结果
~~~
var promise = Promise.reject(new Error("message"));
promise.catch(function (error) {
console.error(error);
});
~~~
如果我们在各种浏览器中执行这段代码,那么在IE8及以下版本则会出现 **identifier not found** 的语法错误。
这是怎么回事呢? 实际上这和 `catch` 是ECMAScript的 [保留字](http://mothereff.in/js-properties#catch) (Reserved Word)有关。
在ECMAScript 3中保留字是不能作为对象的属性名使用的。 而IE8及以下版本都是基于ECMAScript 3实现的,因此不能将 `catch` 作为属性来使用,也就不能编写类似 `promise.catch()` 的代码,因此就出现了 **identifier not found** 这种语法错误了。
而现在的浏览器都是基于ECMAScript 5的,而在ECMAScript 5中保留字都属于 [IdentifierName](http://es5.github.io/#x7.6) ,也可以作为属性名使用了。
> 在ECMAScript5中保留字也不能作为 [Identifier](http://es5.github.io/#x7.6) 即变量名或方法名使用。 如果我们定义了一个名为 `for` 的变量的话,那么就不能和循环语句的 `for` 区分了。 而作为属性名的话,我们还是很容易区分 `object.for` 和 `for` 的,仔细想想我们就应该能接受将保留字作为属性名来使用了。
当然,我们也可以想办法回避这个ECMAScript 3保留字带来的问题。
[点标记法(dot notation)](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation) 要求对象的属性必须是有效的标识符(在ECMAScript 3中则不能使用保留字),
但是使用 [中括号标记法(bracket notation)](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Bracket_notation)的话,则可以将非合法标识符作为对象的属性名使用。
也就是说,上面的代码如果像下面这样重写的话,就能在IE8及以下版本的浏览器中运行了(当然还需要polyfill)。
解决Promise#catch标识符冲突问题
~~~
var promise = Promise.reject(new Error("message"));
promise["catch"](function (error) {
console.error(error);
});
~~~
或者我们不单纯的使用 `catch` ,而是使用 `then` 也是可以避免这个问题的。
使用Promise#then代替Promise#catch
~~~
var promise = Promise.reject(new Error("message"));
promise.then(undefined, function (error) {
console.error(error);
});
~~~
由于 `catch` 标识符可能会导致问题出现,因此一些类库(Library)也采用了 `caught` 作为函数名,而函数要完成的工作是一样的。
而且很多压缩工具自带了将 `promise.catch` 转换为 `promise["catch"]` 的功能, 所以可能不经意之间也能帮我们解决这个问题。
如果各位读者需要支持IE8及以下版本的浏览器的话,那么一定要将这个 `catch` 问题牢记在心中。
- 前言
- 第一章 - 什么是Promise
- 1.1. 什么是Promise
- 1.2. Promise简介
- 1.3. 编写Promise代码
- 第二章 - 实战Promise
- 2.1. Promise.resolve
- 2.2. Promise.reject
- 2.3. 专栏: Promise只能进行异步操作?
- 2.4. Promise#then
- 2.5. Promise#catch
- 2.6. 专栏: 每次调用then都会返回一个新创建的promise对象
- 2.7. Promise和数组
- 2.8. Promise.all
- 2.9. Promise.race
- 2.10. then or catch?
- 第三章 - Promise测试
- 3.1. 基本测试
- 3.2. Mocha对Promise的支持
- 3.3. 编写可控测试(controllable tests)
- 第四章 - Advanced
- 4.1. Promise的实现类库(Library)
- 4.2. Promise.resolve和Thenable
- 4.3. 使用reject而不是throw
- 4.4. Deferred和Promise
- 4.5. 使用Promise.race和delay取消XHR请求
- 4.6. 什么是 Promise.prototype.done ?
- 4.7. Promise和方法链(method chain)
- 4.8. 使用Promise进行顺序(sequence)处理
- 第五章 - Promises API Reference
- 5.1. Promise#then
- 5.2. Promise#catch
- 5.3. Promise.resolve
- 5.4. Promise.reject
- 5.5. Promise.all
- 5.6. Promise.race
- 第六章 - 用語集
- 第七章 - 参考网站
- 第八章 - 关于作者
- 第九章 - 关于译者