Promise 是異步編程的一種解決方案巷懈,ES6 將其寫進了語言標準,統(tǒng)一了用法览绿,原生提供了Promise對象策严。
有了Promise對象,就可以將異步操作以同步操作的流程表達出來饿敲,避免了層層嵌套的回調函數(shù)妻导。
特點
- 對象的狀態(tài)不受外界影響。Promise對象代表一個異步操作怀各,有三種狀態(tài):pending(進行中)倔韭、resolved(已完成,又稱 Fulfilled)和rejected(已失斊岸浴)寿酌。只有異步操作的結果,可以決定當前是哪一種狀態(tài)硕蛹,任何其他操作都無法改變這個狀態(tài)醇疼。
- 一旦狀態(tài)改變,就不會再變法焰,任何時候都可以得到這個結果秧荆。
Promise對象的狀態(tài)改變,只有兩種可能:從pending變?yōu)閞esolved和從pending變?yōu)閞ejected壶栋。 - 一旦新建它就會立即執(zhí)行辰如。
構造函數(shù)
Promise對象是一個構造函數(shù),用來生成Promise實例贵试。
構造函數(shù)接受一個函數(shù)作為參數(shù)琉兜,該函數(shù)的兩個參數(shù)分別是resolve和reject,它們是兩個函數(shù)毙玻。
resolve函數(shù)的作用是將Promise對象的狀態(tài)從pending變?yōu)閞esolved豌蟋,并將異步操作的結果,作為參數(shù)傳遞出去桑滩。
reject函數(shù)的作用是將Promise對象的狀態(tài)從pending變?yōu)閞ejected梧疲,并將異步操作報出的錯誤,作為參數(shù)傳遞出去运准。
let promise = new Promise(function(resolve, reject) {
console.log("Promise")
resolve(42)
})
promise.then(function(value) {
console.log("resolved" + value)
})
console.log("Hi!")
// Promise
// Hi!
// resolved42
實例方法
- then()
then方法的第一個參數(shù)是resolved狀態(tài)的回調函數(shù)幌氮,第二個參數(shù)(可選)是rejected狀態(tài)的回調函數(shù)。
返回的是一個新的Promise實例胁澳,因此可以采用鏈式寫法该互。 - catch()
catch方法是.then(null, rejection)的別名,用于指定發(fā)生錯誤時的回調函數(shù)韭畸。
catch方法返回的還是一個 Promise 對象宇智,因此可以采用鏈式寫法蔓搞。
Promise 對象的錯誤具有“冒泡”性質,會一直向后傳遞随橘,直到被捕獲為止喂分。也就是說,錯誤總是會被下一個
catch捕獲机蔗。
一般來說蒲祈,不要在then方法里面定義 rejected 狀態(tài)的回調函數(shù)(即then的第二個參數(shù)),總是使用catch方法萝嘁。 - finally()
用于指定不管 Promise 對象最后狀態(tài)如何讳嘱,都會執(zhí)行的操作。finally方法的回調函數(shù)不接受任何參數(shù)酿愧。let promise = new Promise(function (resolve, reject) { resolve(42) }) promise.then(function (value) { console.log("resolved" + value) }) promise.catch(function (error) { console.log("rejected" + error) }) promise.finally(function () { console.log("finally") }) //resolved42 finally
靜態(tài)方法
- Promise.all()
用于將多個 Promise 實例沥潭,包裝成一個新的 Promise 實例。
該方法參數(shù)必須具有 Iterator 接口嬉挡,且返回的每個成員都是 Promise 實例钝鸽。
只有每個Promise實例的狀態(tài)變?yōu)閞esolved,返回的新的 Promise 實例狀態(tài)才會變成resolved庞钢。
相反拔恰,只要有一個Promise實例的狀態(tài)變?yōu)閞ejected, 則整個Promise.all調用會立即終止基括,并返回一個rejected的新的promise對象颜懊。
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
reject('報錯了');
})
.then(result => result)
Promise.all([p1, p2])
.then(result => console.log('success' + result))
.catch(e => console.log('error' + e));
//error報錯了
注意點:如果作為參數(shù)的 Promise 實例,自己定義了catch方法风皿,那么它一旦被rejected河爹,并不會觸發(fā)Promise.all()的catch方法。
- Promise.race()
同樣是將多個 Promise 實例桐款,包裝成一個新的 Promise 實例咸这。
方法的參數(shù)與Promise.all方法一樣。
只要有一個實例的狀態(tài)發(fā)生變化魔眨,該函數(shù)就會返回媳维,并使用這個promise對象的值進行resolve或者reject。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('hello'), 2000)
})
.then(result => result)
const p2 = new Promise((resolve, reject) => {
setTimeout(() => reject('world'), 4000)
})
.then(result => result)
Promise.race([p1, p2])
.then(result => console.log('success' + result))
.catch(e => console.log('error' + e));
// successhello
const p1 = new Promise((resolve, reject) => {
setTimeout(() => reject('hello'), 2000)
})
.then(result => result)
.catch(e => e)
const p2 = new Promise((resolve, reject) => {
setTimeout(() => reject('world'), 4000)
})
.then(result => result)
Promise.race([p1, p2])
.then(result => console.log('success' + result))
.catch(e => console.log('error' + e
// successhello
//p1首先狀態(tài)變?yōu)閞ejected遏暴,然后調用自己的catch方法侄刽,返回一個新的Promise 實例(狀態(tài)為resolved),
//所以Promise.race()返回的Promise 實例狀態(tài)為resolved朋凉,調用then方法州丹,所以輸出仍然是successhello。
注意點:如果作為參數(shù)的 Promise 實例侥啤,自己定義了catch方法当叭,那么它一旦被rejected,并不會觸發(fā)Promise.race()的catch方法盖灸。
- Promise.resolve()
返回一個新的 Promise 實例蚁鳖,該實例的狀態(tài)由參數(shù)決定。- 如果參數(shù)是 Promise 實例赁炎,那么Promise.resolve將不做任何修改醉箕、原封不動地返回這個實例。
- 如果參數(shù)是一個thenable對象徙垫,那么Promise.resolve會將這個對象轉為 Promise 對象讥裤,然后就立即執(zhí)行thenable對象的then方法。
- 如果參數(shù)是其他或者不帶參數(shù)姻报,那么返回一個新的 Promise 實例己英,該實例的狀態(tài)為resolved。
Promise.resolve('foo') 等價于 new Promise(resolve => resolve('foo'))
const p2 = new Promise((resolve, reject) => {
reject('world')
})
.then(result => result)
let p3 = Promise.resolve(p2)
console.log(p3 === p2) // true 原封不動地返回p2
let thenable = {
then: function (resolve, reject) {
reject(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function (value) {
console.log('then' + value);
});
p1.catch(function (error) {
console.log('catch' + error);
// catch42 Promise.resolve將thenable轉為Promise對象吴旋,
//然后執(zhí)行thenable的then方法损肛,Promise對象的狀態(tài)變?yōu)閞ejected,所以執(zhí)行p1.catch方法荣瑟。
});
- Promise.reject()
返回一個新的 Promise 實例治拿,該實例的狀態(tài)為rejected。
const p = Promise.reject('出錯了'); 等同于 const p = new Promise((resolve, reject) => reject('出錯了'))