Promise
對象是一個代理對象(代理一個值),被代理的值在Promise
對象建立時多是未知的。javascript
Promise
對象有三種狀態:pending
(初始狀態)、fulfilled
(成功狀態)、rejected
(失敗狀態)。java
Promise
對象的狀態一旦由pending
變爲fulfilled
或rejected
將沒法再更改。promise
Promise
對象的狀態變爲fulfilled
後,經過then()
方法執行回調函數;狀態變爲rejected
後,經過catch()
方法執行回調函數。dom
在 ES2018 中引入了finally()
,表示該Promise
執行結束後(不管是"then
"仍是"catch
"致使的結束)都會執行傳入finally
方法的回調函數,回調函數無參數。異步
經過new
運算符能夠建立Promise
實例,惟一參數是帶有 resolve
和reject
兩個參數的 executor
函數。resolve
和reject
函數被調用時,分別將Promise
的狀態改成fulfilled
(完成)或rejected
(失敗),兩個函數都接受一個參數,做爲成功(或失敗)的信息傳遞給對應的處理方法(then
或catch
)。函數
let p = new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('resolve');
} else {
reject('reject');
}
}, 1000);
});複製代碼
上述例子中,1 秒後隨機把Promise
對象的狀態改成fulfilled
(完成)或rejected
(失敗)。ui
被建立的Promise
對象會當即執行executor
函數,若是咱們還須要在該異步函數結束後再作點什麼,就須要調用Promise
對象的then()
、catch()
和finally()
方法。(三個方法都會返回一個新的Promise
對象,所以能使用"鏈式操做")spa
接上例子:prototype
p.then(res => {
console.log(res); // 'resolve'
}).catch(err => {
console.log(err); // 'reject'
}).finally(()=>{
console.log('finally'); // 一定執行
});複製代碼
能夠看出,then()
和catch()
方法傳入的是一個回調函數,該回調函數有惟一參數,對應的是resolve
和reject
函數傳入的參數。finally()
一樣是傳入一個對調函數,不一樣的是該回調函數無參數。代理
場景1:多個Promise
須要依次執行。(Promise.prototype.then()
能夠傳入另外一個Promise對象)
const promise1 = new Promise(...);
const promise2 = new Promise(...);
const promise3 = new Promise(...);
// promise1成功執行後再執行promise2,再是promise3
promise1.then(promise2).then(promise3);複製代碼
場景2:多個Promise
須要都成功。(靜態方法:Promise.all()
)
const promise1 = new Promise(...);
const promise2 = new Promise(...);
const promise3 = new Promise(...);
// promise1/2/3 均成功後再執行 then ( 其中一個失敗也不會執行 then )
Promise.all([promise1, promise2, promise3]).then(callback(){...});複製代碼
場景3:多個Promise
只須要其中一個成功。(靜態方法:Promise.race()
)
const promise1 = new Promise(...);
const promise2 = new Promise(...);
const promise3 = new Promise(...);
// promise1/2/3 任意一個成功後執行 then
Promise.race([promise1, promise2, promise3]).then(callback(){...})
複製代碼
Promise.resolve()
用於生成一個狀態爲fulfilled
的Promise
對象。其參數與.prototype.resolve()
一致。
let p1 = Promise.resolve('resolve');
// 等效以下代碼
let p2 = new Promise((resolve, reject) => {
resolve('resolve');
});複製代碼
Promise.reject()
用於生成一個狀態爲rejected
的Promise
對象。其參數與.prototype.reject()
一致。
let p1 = Promise.reject('resolve');
// 等效以下代碼
let p2 = new Promise((resolve, reject) => {
reject('resolve');
});複製代碼
其實上面的介紹中,徹底沒有說起then()
的第二個參數,由於其做用與catch()
方法一致。看下面例子:
let p = new Promise((resolve, reject) => {
reject('reject');
})
p.then(res => { }, err => {
console.log(err); // 'reject'
});
p.catch(err => {
console.log(err); // 'reject'
});
複製代碼
當then()
/catch()
/finally()
不傳入參數,都會返回與原Promise
對象相同(但不相等)的新Promise
對象。看以下例子:
// 不傳參的"then"
let p1 = Promise.resolve('resolve');
let p2 = p1.then();
p2.then(res => {
console.log(res); // 'resolve'
});
console.log(p1 === p2); // false
// 不傳參的"catch"
let p3 = Promise.reject('reject');
let p4 = p3.catch();
p4.catch(res => {
console.log(res); // 'reject'
});
console.log(p3 === p4); // false
// 不傳參的"finally"
let p5 = Promise.resolve('resolve');
let p6 = p5.finally();
p6.then(res => {
console.log(res); // 'resolve'
});
console.log(p5 === p6); // false
複製代碼
當then()
或catch()
的參數是有返回值的回調函數A
,then()
或catch()
會返回一個狀態爲fulfilled
的Promise
對象。新Promise
對象的then()
方法的回調函數的參數就是回調函數A
的返回值。
注意,狀態爲reject
的Promise
對象在then()
的第一個對調函數返回會致使報錯。
注意,finally()
的對調函數"return
"並不會影響新的Promise
對象的then()
或catch()
方法的回調函數的參數值。
若是以爲文字描述有點繞,看下面例子:
// 'resolve'狀態被處理後的'return'
Promise.resolve('resolve').then(() => {
return 'return1'
}).then(res => {
console.log(res)
}); // 'return1'
// 'reject'狀態被處理後的'return'
Promise.reject('resolve').catch(() => {
return 'return2'
}).catch(err => {
console.log('catch:', err)
}).then(res => {
console.log('then:', res)
}); // 'then: return2'
// 'finally'的'return'只會返回與原promise相同的對象
Promise.resolve('resolve').finally(() => {
return 'return3'
}).then(res => {
console.log(res)
}); // 'resolve'
// 'reject'狀態未被處理的'return'
Promise.reject('reject').then(() => {
return 'return4'
}).then(res => {
console.log(res);
}); // 報錯!!複製代碼
resolve()
(包括Promise.reject()
和Promise.prototype.reject()
)除了上面介紹的用法,還能傳入thenable
(即,帶有then方法的對象),返回的Promise
對象的最終狀態由then
方法執行決定。
注意,thenable
的then()
方法只有傳入惟一一個回調函數纔會被執行,其餘參數會被忽略。
看以下例子:
let thenable = {
then(cb1, cb2) {
cb1('cb1');
cb2('cb2');
}
}
// Promise.resolve()
Promise.resolve(thenable).then(
res1 => {
console.log(res1); // 'cb1'
},
res2 => {
console.log(res2); // 不會執行
}
).catch(err => {
console.log(err); // 不會執行
});
// Promise.prototype.resolve()
new Promise((resolve, reject) => {
resolve(thenable);
}).then(res => {
console.log(res); // 'cb1'
});複製代碼