在?[前面的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的問題
[](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
- 第六章 - 用語集
- 第七章 - 參考網站
- 第八章 - 關于作者
- 第九章 - 關于譯者