Promise 就是一個對象,用來傳遞異步操作的消息。
用法:
1、創(chuàng)建一個promise實(shí)例
const promise = new Promise((resolve, reject) => {
????// ... some code
????If (/*異步操作成功*/) {
????????resolve(value);
????} else {
????????reject(error);
? ? }
});
promise 構(gòu)造函數(shù)接收一個函數(shù)作為參數(shù),該函數(shù)的兩個參數(shù)分別是resolve和reject。它們是兩個函數(shù),由JavaScript引擎提供,不用自己部署。
resolve函數(shù)的作用是,將Promise對象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸腜ending變?yōu)镽esolved),在異步操作成功時調(diào)用,并將異步操作的結(jié)果作為參數(shù)傳遞出去;reject函數(shù)的作用是,將Promise對象的狀態(tài)從“未完成”變?yōu)椤笆 保磸腜ending變?yōu)镽ejected)在異步操作失敗時調(diào)用,并將異步操作報出的錯誤作為參數(shù)傳遞出去。
2、Promise實(shí)例生成后,可以用then方法分別指定Resolved 和Rejected狀態(tài)的回調(diào)函數(shù)
promise.then((value) => {
????// success
}, (error) => {
????// failure
});
then方法可以接受兩個回調(diào)函數(shù)作為參數(shù)。第一個回調(diào)函數(shù)是Promise對象的狀態(tài)變?yōu)镽esolved時調(diào)用,第二個回調(diào)函數(shù)是Promise對象的狀態(tài)變?yōu)镽ejected時調(diào)用(可選)。
3、用Promise對象實(shí)現(xiàn)的AJAX操作的例子
const getJSON = (url) => {
????const promise = new Promise((resolve, reject) => {
????????const client = new XMLHttpRequest();
????????client.open(‘GET’, url);
????????client.onreadystatechange = handler;
????????client.responseType = “json”;
????????client.setRequestHeader(“Accept”, “application/json”);
????????client.send();
????????const 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((json) => {
????Console.log(‘Contents: ‘ + json);
}, (error) => {
????Console.error(‘出錯了’, error);
});
4、如果調(diào)用resolve函數(shù)和reject函數(shù)時帶有參數(shù),這些參數(shù)會被傳遞給回調(diào)函數(shù)。reject函數(shù)的參數(shù)通常是Error對象的實(shí)例,表示拋出的錯誤;resolve函數(shù)的參數(shù)除了正常的值,還可能是另一個Promise實(shí)例,表示異步操作的結(jié)果有可能是一個值,也有可能是另一個異步操作。
const p1 = new Promise((resolve, reject) => {
? ? // ...
});
const p2 = new Promise((resolve, reject) => {
? ? // ...
? ? resolve(p1);
});
p1的狀態(tài)會傳遞給p2
5、Promise.prototype.then()
(1)then方法返回的是一個新的Promise實(shí)例(不是原來那個Promise實(shí)例),因此可以采用鏈?zhǔn)綄懛?
第一個回調(diào)函數(shù)完成以后,會將返回結(jié)果作為參數(shù)傳入第二個回調(diào)函數(shù)。
getJSON("/posts.json").then(json => {
? ? return json.post;
}).then(post => {
? ? // ...
});
(2)采用鏈?zhǔn)降膖hen可以指定一組按照次序調(diào)用的回調(diào)函數(shù)。如果前一個回調(diào)函數(shù)返回的是一個Promise對象(即有異步操作),后一個回調(diào)函數(shù)就會等待該P(yáng)romise對象的狀態(tài)發(fā)生變化后再被調(diào)用。
getJSON("/post/1.json").then(
? ? post => getJSON(post.commentURL)
).then(
? ? comments => console.log("Resolved: " + comments),
? ? err => console.log("Rejected: " + err)
);
6、Promise.prototype.catch()
(1)Promise.prototype.catch方法是 .then(null, reject)的別名,用于指定發(fā)生錯誤時的回調(diào)函數(shù)。
getJSON("/posts.json").then(posts => {
? ? // ...
}).catch(error => {
? ? // 處理前一個回調(diào)函數(shù)運(yùn)行時發(fā)生的錯誤
? ? console.log('There is an error occured', error);
});
(2)Promise對象的錯誤具有“冒泡”性質(zhì),會一直向后傳遞,直到被捕獲為止
getJSON("/post/1.json").then(post => {
? ? return getJSON(post.commentURL);
}).then(comments => {
? ? // some code
}).catch(error => {
// 處理前面3個Promise產(chǎn)生的錯誤
});
(3)catch方法返回的還是一個Promise對象,因此后面還可以接著調(diào)用then方法
7、Promise.all()
Promise.all 方法用于將多個Promise實(shí)例包裝成一個新的Promise實(shí)例
const p = Promise.all([p1, p2, p3]);
(1)參數(shù)不一定是數(shù)組,但必須具有Iterator接口
(2)p1 p2 p3都是Promise實(shí)例
(3)p的狀態(tài)由p1、p2、p3決定,分兩種情況
(3.1)只有p1、p2、p3的狀態(tài)都變成Resolved,p的狀態(tài)才會變成Resolved。此時p1、p2、p3的返回值組成一個數(shù)組,傳遞給p的回調(diào)函數(shù)
(3.2)只要p1、p2、p3中有一個被Rejected,p的狀態(tài)就變成Rejected。第一個被Rejected的實(shí)例的返回值會傳遞給p的回調(diào)函數(shù)
8、Promise.race()
Promise.race()方法同樣是將多個Promise實(shí)例包裝成一個新的Promise實(shí)例。
const p = Promise.race([p1, p2, p3]);
只要p1、p2、p3中有一個實(shí)例狀態(tài)改變,p的狀態(tài)就跟著改變。那個先改變的Promise實(shí)例的返回值,就傳遞給p的回調(diào)函數(shù)
9、Promise.resolve() 將現(xiàn)有對象轉(zhuǎn)為Promise對象
10、Promise.reject() 返回一個新的Promise實(shí)例,狀態(tài)為Rejected