在我們開始正式介紹之前,我們想看看Javascript Promise的樣子:
var p = new Promise(function(resolve, reject) {
resolve("hello world");
});
p.then(function(stren(function(stren(function(str. ) {
alert(str);
});
1. then()回傳一個Forked Promise
以下兩段程式碼有什麼差別呢?
// Exhibit A
(/*...*/);
p.then(func1);
p.then(func2);
// Exhibit B
var p = new Promise(/ *...*/);
p.then(func1)
.then(func2);
如果你認真以上兩段程式碼等同的話,那麼Promises只不過是一個一維的回調函數數組。然而,其實不是這樣的。每一個then()呼叫都回傳一個forked promise。因此,在ExhibitA中,如果func1()拋出一個異常,func2()仍舊正常呼叫。
在ExhibitB中,如果func1()拋出一個錯誤,fun2()將不會被調用,因為第一個調用返回了一個新的promise,這個在func1()中會被拒絕。結果是func2()被跳過。
總結:promises可以被fork成多個路徑,類似複雜的流程圖。
2. Callback應該傳遞結果
當你執行下面程式碼的時候什麼會得到警告提示呢?
var p = new Promise(function(resolve, rejunction) {
resolve("hello world");
});
p.then(function(str) {})
.then(function(str) {
alert (str);
});
第二個then()中的alert沒有顯示任何內容。這是因為回呼函數,在promise的上下文中,因為結果的變化並沒有回調函數。 promise期望你的回呼函數會傳回同樣的結果或回傳一個替換結果,然後被傳遞到下一個回呼函數。
類似使用adpater來變化結果,如下:
var feetToMetres = function(ft) { return ft*12*0.0254 };
var p = new Promise(/*...*/);
p.then(feetToMetres)
.then(function(metres) {
alert(metres);
});
3. 只有來自上一層的異常可以被捕捉
這兩段程式碼有什麼差別?
// Exhibit A resolve("hello world");
})
.then(
function(str) {
throw new Error("uhoh"); > },
undefined
)
.then(
undefined,
function(error) {
alert(error);
// Exhibit B
new Promise(function(resolve, reject) {
resolve("hello world");
}).then(
function(str
throw new Error("uh oh");
},
function(error) {
alert(error);
}
alert(error);
}
在第二段程式碼中,回呼函數和錯誤回呼函數是同一個層次,表示當異常在回呼中拋出,將不會被捕捉。事實上,第二段程式碼的錯誤回呼將只會在promise為拒絕狀態或promise本身出錯的情況下拋出
4. 錯誤可以被恢復
在一個錯誤回呼函數中,如果你不重新拋出錯誤,promise會假設你已經從錯誤中恢復,並且反轉成為已解決狀態。在下一個例子中,"i'm saved" 將會被顯示,這是因為在第一個then()中的錯誤回呼沒有重新拋出異常。
複製程式碼
程式碼如下:
var p = new Promise(function(resolve, reject) {
reject(new Error("pebkac"));
});
p.then(
undefined,
function(error) { }
)
.then(
function(str) {
alert("I am saved!")
alert("I am saved!")
🎜> function(error) {
alert("Bad computer!");
}
);
Promise可以被視為洋蔥上的層次。每一個then()再加一個層次到洋蔥。每一個層次代表了一個被處理的活動。當層次結束,結果被認為已經修復並且為下一個層次做好了準備。
5. Promises可以被暫停
因為你已經準備好了在一個then()方法中執行,並不意味著你不能夠暫停並且提前運行其他。 為了暫停目前的promise,或讓它等待以便另外一個promise完成,簡單在then()中返回另外一個promise。
var p = new Promise(/*... /);
p.then(function(str) {
if(!loggedIn) {
return new Promise(/*...*/);
}
}
})
.then(function(str) {
alert("Done.");
})
在前面程式碼中,直到新的promise解析後提示才會出現。這是一個方便的方式在已存在的非同步程式碼路徑中來引入更多地依賴。例如,你可能發現使用者session已經timeout,而且你可能會想要在繼續前面的程式碼路徑前初始化第二個登陸。
6. Resolved Promises並不會立刻執行
運行下面程式碼會得到提示框麼?
程式碼如下:
function runme() {
function runme() {
function runme() {
;
new Promise(function(resolve) {
resolve();
}) .then(function() { ); alert(i);}因為promise立刻被解析,然後then()方法立刻執行,所以你可能會認為會探出提示2。但是promise定義要求所有的呼叫都被強制非同步。因此提示會在被修改前產生。