Promise基本模型
var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
var client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
function handler() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出錯了', error);
});
`
Promise是一個容器,保存著將來才會發(fā)生的事件。Promise一開始是Pending狀態(tài),調(diào)用resolve函數(shù)變成Resolved狀態(tài),或者調(diào)用Reject函數(shù)變成Rejected狀態(tài),狀態(tài)是不可逆的。
上面代碼中resolve、reject兩個函數(shù)由語言框架提供,我們只需要調(diào)用promise對象的then函數(shù)指定Resolved狀態(tài)和Reject狀態(tài)的回調(diào)函數(shù)。promise對象的catch只是then(null, rejection)的別名。
then鏈式調(diào)用
getJSON('/post/1.json').then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// 處理前面三個Promise產(chǎn)生的錯誤
});
then方法返回的也是一個新的Promise對象(不是前面那個),所以then方法可以寫成鏈式調(diào)用。后一個then方法指定的回調(diào)函數(shù),會等到前面的Promise狀態(tài)發(fā)生改變時才被調(diào)用。
- 前一個then方法指定的回調(diào)函數(shù),返回一個普通對象,該對象會作為參數(shù)傳給下一個then指定的回調(diào)函數(shù)
- 前一個then方法指定的回調(diào)函數(shù),返回一個Promise對象,后一個回調(diào)函數(shù)會等該Promise狀態(tài)改變才會被調(diào)用。
- 如果前面Promise跑出異常,會直接向后傳遞,知道找到一
catch方法指定的回調(diào)函數(shù),去處理異常。如果沒有catch函數(shù),異常并不會拋到外層。
Promise.all()
// 生成一個Promise對象的數(shù)組
var promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON("/post/" + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
只有所有的Promise對象狀態(tài)都變成Resolved,會將所有的返回結(jié)果組成一個數(shù)組作為參數(shù),調(diào)用then方法指定的回調(diào)函數(shù);否則會將第一個變成Rejected狀態(tài)的Promise的返回值,傳遞給catch指定的毀掉函數(shù)。
Promise.race()
'' var p = Promise.race([p1, p2, p3]);
跟Promise.all不同的是,將第一個改變狀態(tài)的Promise實例返回值作為參數(shù)去回調(diào),而不是等到所有Promise實例黃臺都改變。
Promise.resolve()
將入?yún)⑥D(zhuǎn)化成Promise對象,入?yún)㈩愋筒煌?/p>
- 入?yún)⒓词荘romise實例:此時直接入?yún)⒎祷?,不做修?/li>
- 入?yún)⑹?code>thenable對象(有then方法),會立即執(zhí)行
then方法。這個主要針對異步操作。 - 入?yún)⑹菦]有
then方法的對象,或者不是對象。返回的Promise實例一生成就是Resolved狀態(tài),then指定的回調(diào)函數(shù)會被立即執(zhí)行。 - 沒有入?yún)?,?.
上面提到的立即執(zhí)行,是在本輪時間循環(huán)結(jié)束時執(zhí)行。
上面的Promise.all、Promise.race如果參數(shù)中包含非Promise,對象,會被嗲用Promise.resolve轉(zhuǎn)換成Promise對象。之前的鏈式調(diào)用,也是調(diào)用該方法生成新的Promise對象。
Promise.reject
不同于Promise.resolve,該方法參數(shù)會原樣作為reject回調(diào)的入?yún)ⅰ?/p>