promsie是異步編程的一種解決方案肩祥,總得來說promise是一個(gè)對象萍膛,從它可以獲取異步操作的消息雨让。它具備以下兩個(gè)特點(diǎn):
- 對象的狀態(tài)不受外界影響。promise對象代表一個(gè)異步操作,有三種狀態(tài):pending(進(jìn)行中),fulfilled(已成功)和rejected(失敗)夹纫。只有異步操作的結(jié)果咽瓷,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作無法改變這個(gè)promise舰讹。
- 一旦狀態(tài)改變茅姜,就不會(huì)改變,任何時(shí)候都可以得到這個(gè)結(jié)果月匣。promise只有兩種過度狀態(tài)
pending => fulfilled钻洒,pending =>rejected。
后續(xù)resolved統(tǒng)一只指fulfilled狀態(tài)锄开。
注意:無法取消promise素标,一旦新建立即執(zhí)行,無法中途取消
常用用法
Promise 構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù)萍悴,我們可以看下示例
const promise = new Promise(function(resolve,reject){
if(成功) {
resolve(2); //將狀態(tài)pending ->成功
console.log(1); // 這個(gè)會(huì)先執(zhí)行头遭,因?yàn)閞esolve()是在本輪事件的末尾執(zhí)行,總是晚于本輪循環(huán)的同步
} else {
reject(New Error('fail')); //將狀態(tài)pending ->失敗
}
})
promise.then(function(value){
//success
console.log(value); //2
},function(error){
// failure
console.log(error);
})
- then方法返回的是一個(gè)新的promsie實(shí)列癣诱,所以可以采用鏈?zhǔn)綄懛莆磘hen方法后面再調(diào)用then。
- 一般來說調(diào)用resolve和reject以后撕予,Promise使命就完成了享潜,所以建議直接return resolve或return reject;
catch
通常我們寫promise嗅蔬,估計(jì)很多人平時(shí)都沒寫這個(gè)剑按,這個(gè)因?yàn)槲覀儫o法保證這個(gè)promise實(shí)例運(yùn)行正常,所以需要一個(gè)方法來指定發(fā)生錯(cuò)誤時(shí)的回調(diào)(注意可以不是reject)澜术;
getJSON('/posts.json').then(function(posts){
// getJSON()方法返回一個(gè) Promise 對象,resolve狀態(tài)執(zhí)行這個(gè)回調(diào)
console.log('resolved')
}).catch(function(error){
// Promise 對象拋出錯(cuò)誤艺蝴,就會(huì)被catch捕獲
console.log('發(fā)生錯(cuò)誤!',error)
})
promise對象錯(cuò)誤具有冒泡性質(zhì)
getJSON('/post/1.json').then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// 處理前面三個(gè)Promise產(chǎn)生的錯(cuò)誤
});
一般來說,不要在then()方法里面定義 Reject 狀態(tài)的回調(diào)函數(shù)(即then的第二個(gè)參數(shù))鸟废,總是使用catch方法猜敢。
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error // 不可以捕獲成功回調(diào)里的錯(cuò)誤
});
// good
promise
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error 可以捕獲到then里面執(zhí)行的錯(cuò)誤
});
catch()方法返回的還是一個(gè) Promise 對象,因此后面還可以接著調(diào)用then()方法盒延。
finally
finally()方法用于指定不管 Promise 對象最后狀態(tài)如何缩擂,都會(huì)執(zhí)行的操作。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
finally方法注意沒有參數(shù)添寺,不依賴于Promise的執(zhí)行結(jié)果,不管掐面是fulfilled還是rejected狀態(tài)胯盯,都不會(huì)影響他的執(zhí)行,其實(shí)本質(zhì)上是then方法的特列
promise
.finally(() => {
// 語句
});
// 等同于
promise
.then(
result => {
// 語句
return result;
},
error => {
// 語句
throw error;
}
);
下面簡單的講幾個(gè)常用的promise方法
- Promsie.all([p1,p2,p3]) 用于多個(gè)promise實(shí)例,包裝成一個(gè)新的Promsie计露,接受具有 Iterator 接口博脑,且返回的每個(gè)成員都是 Promise 實(shí)例的參數(shù)(常見就是數(shù)組)憎乙。全成功則成功,一個(gè)失敗則會(huì)失敗叉趣。
小提問泞边?如果promise.all()其中中間有一個(gè)或者多個(gè)錯(cuò)誤,我還是想執(zhí)行成功后的回調(diào)疗杉,怎么辦
給每個(gè)Promise實(shí)例都定義catch方法
- Promise.race([p1, p2, p3]); 阵谚,只要p1、p2烟具、p3之中有一個(gè)實(shí)例率先改變狀態(tài)椭蹄,這個(gè)實(shí)例的狀態(tài)就跟著改變。那個(gè)率先改變的 Promise 實(shí)例的返回值净赴,就傳遞給p的回調(diào)函數(shù)
后續(xù)還有挺多的方法。