從代碼上乍一看,?`aPromise.then(...).catch(...)`?像是針對最初的?`aPromise`?對象進行了一連串的方法鏈調用。
然而實際上不管是?`then`?還是?`catch`?方法調用,都返回了一個新的promise對象。
下面我們就來看看如何確認這兩個方法返回的到底是不是新的promise對象。
~~~
var aPromise = new Promise(function (resolve) {
resolve(100);
});
var thenPromise = aPromise.then(function (value) {
console.log(value);
});
var catchPromise = thenPromise.catch(function (error) {
console.error(error);
});
console.log(aPromise !== thenPromise); // => true
console.log(thenPromise !== catchPromise);// => true
~~~
`===`?是嚴格相等比較運算符,我們可以看出這三個對象都是互不相同的,這也就證明了?`then`?和?`catch`?都返回了和調用者不同的promise對象。

我們在對Promise進行擴展的時候需要牢牢記住這一點,否則稍不留神就有可能對錯誤的promise對象進行了處理。
如果我們知道了?`then`?方法每次都會創建并返回一個新的promise對象的話,那么我們就應該不難理解下面代碼中對?`then`?的使用方式上的差別了。
~~~
// 1: 對同一個promise對象同時調用 `then` 方法
var aPromise = new Promise(function (resolve) {
resolve(100);
});
aPromise.then(function (value) {
return value * 2;
});
aPromise.then(function (value) {
return value * 2;
});
aPromise.then(function (value) {
console.log("1: " + value); // => 100
})
// vs
// 2: 對 `then` 進行 promise chain 方式進行調用
var bPromise = new Promise(function (resolve) {
resolve(100);
});
bPromise.then(function (value) {
return value * 2;
}).then(function (value) {
return value * 2;
}).then(function (value) {
console.log("2: " + value); // => 100 * 2 * 2
});
~~~
第1種寫法中并沒有使用promise的方法鏈方式,這在Promise中是應該極力避免的寫法。這種寫法中的?`then`?調用幾乎是在同時開始執行的,而且傳給每個?`then`?方法的?`value`?值都是?`100`?。
第2中寫法則采用了方法鏈的方式將多個?`then`?方法調用串連在了一起,各函數也會嚴格按照 resolve → then → then → then 的順序執行,并且傳給每個?`then`?方法的?`value`?的值都是前一個promise對象通過?`return`?返回的值。
下面是一個由方法1中的?`then`?用法導致的比較容易出現的很有代表性的反模式的例子。
??`then`?的錯誤使用方法
~~~
function badAsyncCall() {
var promise = Promise.resolve();
promise.then(function() {
// 任意處理
return newVar;
});
return promise;
}
~~~
這種寫法有很多問題,首先在?`promise.then`?中產生的異常不會被外部捕獲,此外,也不能得到?`then`?的返回值,即使其有返回值。
由于每次?`promise.then`?調用都會返回一個新創建的promise對象,因此需要像上述方式2那樣,采用promise chain的方式將調用進行鏈式化,修改后的代碼如下所示。
`then`?返回返回新創建的promise對象
~~~
function anAsyncCall() {
var promise = Promise.resolve();
return promise.then(function() {
// 任意處理
return newVar;
});
}
~~~
關于這些反模式,詳細內容可以參考?[Promise Anti-patterns](http://taoofcode.net/promise-anti-patterns/)?。
這種函數的行為貫穿在Promise整體之中, 包括我們后面要進行說明的?[Promise.all](http://liubin.github.io/promises-book/#ch2-promise-all)?和?[Promise.race](http://liubin.github.io/promises-book/#ch2-promise-race)?,他們都會接收一個promise對象為參數,并返回一個和接收參數不同的、新的promise對象。
- 前言
- 第一章 - 什么是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
- 第六章 - 用語集
- 第七章 - 參考網站
- 第八章 - 關于作者
- 第九章 - 關于譯者