【ES6.0】- Promise對象
文章目錄
- 【ES6.0】- Promise對象
- 一、概述
- 二、Promise狀態
- 三、Promise方法
- 3.1 Promise.prototype.then方法:鏈式操作
- 3.2 Promise.prototype.catch方法:捕捉錯誤
- 3.3 Promise.race方法:捕捉錯誤
- 3.4 Promise.any()
- 3.5 Promise.all()
- 3.6 Promise.allSettled()
- 四、總結
一、概述
Promise是異步編程的一種解決方案,是一種javascript處理異步操作的一種常見方式。Promise是一種處理異步操作的設計模式,提供了一種更結構化,更可靠的方式來處理異步任務。
二、Promise狀態
Promise異步操作有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。除了異步操作的結果,任何其他操作都無法改變狀態。
Promise對象只有:從pending變為fulfilled和從penging變為rejected的狀態改變。只要處于fulfilled和rejected,狀態就不會再變為resolved (已定型)。
Promise狀態演示
const pm1=new Promise(function(resolve,reject){resolve('resolve1')resolve('resolve2')
})const pm2=new Promise(function(resolve,reject){resolve('resolve3')reject('reject1')
})pm1.then(function(value){console.log('pm1->then->value',value) //resolve1
})pm2.then(function(value){console.log('pm2->then->value',value) // resolve3
})
狀態的缺點:
無法取消Promise,一旦新建它就會立即執行,無法中途取消。如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。當處于pending狀態時,無法得知目前進展到哪一個階段。
三、Promise方法
3.1 Promise.prototype.then方法:鏈式操作
Promise.prototype.then方法返回的是一個新的Promise對象,因此可以采用鏈式寫法:
const pm1=new Promise(function(resolve,reject){resolve('resolve-01')
})
pm.then(function(value){console.log(value)return value+'-02'
}).then(function(value){console.log(value)return value+'-03'
}).then(function(value){console.log(value)
})
輸出結果
resolve-01
resolve-01-02
resolve-01-02-03
上面的代碼使用then方法,依次指定了兩個回調函數。第一個回調函數完成以后,會將返回結果作為參數,傳入第二個回調函數,第二個回調函數完成以后,會把返回值作為參數出入給第三個回調函數;依次直至結束。
如果前一個回調函數返回的是Promise對象,這個時一個回調函數就會等待該Promise對象有了運行結果才進一步調用
const pmFun=(param)=>{return new Promise((resolve,reject)=>{setTimeout(()=>{if(param<100){resolve('輸入值<100,傳入值為:'+param)}else{reject('輸入值>100,傳入值為:'+param)}},2000)})
}
pmFun(50).then((resp)=>{console.log('then-1',resp)return pmFun(83)
}).then((resp)=>{console.log('then-2',resp)
})
輸出結果:
輸入值<100,傳入值為:50
輸入值<100,傳入值為:82
Promisei的這種設計使得嵌套的異步操作,可以被很容易得到改寫,從回調函數的“橫向發展”改為“向下發展”。
3.2 Promise.prototype.catch方法:捕捉錯誤
Promise.prototype.catch方法是Promise.prototype.then(null,rejection)的別名,用于指定發生錯誤時回調函數。
const pmFun=(param)=>{return new Promise((resolve,reject)=>{setTimeout(()=>{if(param<100){resolve('輸入值<100,傳入值為:'+param)}else{reject('輸入值>100,傳入值為:'+param)}},2000)})
}
pmFun(50).then((resp)=>{console.log('then-1',resp)return pmFun(83)
}).then((resp)=>{console.log('then-1',resp)
}).catch((resp)=>{console.log('catch',resp)
})
Promise對象的錯誤具有“冒泡”性質,會一直向后傳遞,直到被捕捉為止,也就是說,錯誤總是會被下一個catch語句捕捉。
3.3 Promise.race方法:捕捉錯誤
Promise.race()方法允許我們同時發起多個異步操作,并在其中一個操作解決(fulfilled)或拒絕(rejected)時得到結果。它的語法如下:
Promise.race([promise1,promise2,..])
其中,promise1,promise2等為Promise對象數組。新的Promise的狀態將與第一個解決或拒絕的Promise的狀態相同。
const p1=new Promise((resolve,reject)=>{setTimeout(resolve,2000,'one')
})
const p2=new Promise((resolve,reject)=>{setTimeout(resolve,1000,'two')
})
const p3=new Promise((resolve,reject)=>{setTimeout(resolve,3000,'three')
})
const p3=new Promise((resolve,reject)=>{setTimeout(resolve,3000,'three')
})
Promise.race([p1,p2,p3]).then((resp)=>{console.log('then',resp)
}).catch((resp)=>{console.log('catch',resp)
})
運行結果
then two
race函數返回一個Promise,它將與第一個傳遞的promise相同的完成方式被完成。它可以是完成(resolves),也可以是失敗(rejects),這要取決第一個完成的方式是兩個中的哪個。
如果傳的迭代是空的,則返回的 promise 將永遠等待。
如果迭代包含一個或多個非承諾值和/或已解決/拒絕的承諾,則 Promise.race
將解析為迭代中找到的第一個值。
race在遇見立即執行的reject時并沒有像any一樣繼續等待resolve的返回,而是直接返回了reject的內容。
3.4 Promise.any()
Promise.any()接收一個由Promise所組成的可迭代iterable對象,該方法會返回一個新的promise,一旦迭代對象內的任意一個promise變成了兌現狀態,那么由該方法所有返回的promise就會變成兌現狀態,并且它的兌現值就是可迭代對象內的首先兌現的promise的兌現值。
如果可迭代對象內的promise最終都沒有兌現(即所有 promise 都被拒絕了),,那么該方法所返回的 promise 就會變成拒絕狀態,并且它的拒因會是一個 AggregateError 實例,這是 Error 的子類,用于把單一的錯誤集合在一起。
const p1=new Promise((resolve,reject)=>{setTimeout(resolve,2000,'one')
})
const p2=new Promise((resolve,reject)=>{setTimeout(resolve,1000,'two')
})
const p3=new Promise((resolve,reject)=>{setTimeout(resolve,3000,'three')
})
const p4=new Promise((resolve,reject)=>{reject('P4->reject')
})
Promise.race([p1,p2,p3,p4]).then((resp)=>{console.log('then',resp)
}).catch((resp)=>{console.log('catch',resp)
})
tren,two
只要參數實例有一個變成fulfilled狀態,包裝實例就會變成fulfilled狀態;如果所有參數實例都變成rejected狀態,包裝實例就會變成rejected狀態。
Promise.any()
和Promise.race()
方法很像,只有一點不同,就是Promise.any()
不會因為某個Promise變成rejected狀態而結束,必須等到所有參數Promise變成rejected狀態才會結束。
3.5 Promise.all()
Promise.all()方法接收一個 Promise的iterable類型的輸入。并且只返回一個Promise實例,那個輸入的所有promise的resolve回調的結果是一個數組。
Promise的resolve回調執行是在所有輸入的promise的resolve回調都結束,或者輸入的iterable里沒有promise了的時候。
它的reject回調執行時,只要任何一個輸入的promise的reject回調執行或者執行或者輸入不合格的promise就會立即拋出錯誤,并且reject的是第一個拋出的錯誤信息。
var p1 = new Promise((resolve, reject) => {setTimeout(resolve, 1000, 'p1->one');
});
var p2 = new Promise((resolve, reject) => {setTimeout(resolve, 2000, 'p2->two');
});
var p3 = new Promise((resolve, reject) => {setTimeout(resolve, 3000, 'p3->three');
});
var p4 = new Promise((resolve, reject) => {setTimeout(resolve, 4000, 'p4->four');
});
var p5 = new Promise((resolve, reject) => {reject('reject');
});Promise.all([p1, p2, p3, p4, p5]).then(values => {console.log(values);
}, reason => {console.log(reason)
});
then ['p1->one','p2->two','p3->three','p4->four']
Promise.all()
主要應用需要所有異步任務都同時進行并且完成時可以使用all方法。
3.6 Promise.allSettled()
Promise.allSettled()
方法返回一個在所有給定的promise都已經fulfilled或rejected后的pronise,并帶有一個對象數組,每個對象表示對應的promise結果。
當您有多個彼此不依賴的異步任務成功完成時,或者您總是想知道每個promise的結果時,通常使用它。
相比之下,Promise.all()
更適合彼此相互依賴或者在其中任何一個reject時立即結束。
var p1 = new Promise((resolve, reject) => {setTimeout(resolve, 4000, 'p1->one');
});
var p2 = new Promise((resolve, reject) => {setTimeout(resolve, 3000, 'p2->two');
});
var p3 = new Promise((resolve, reject) => {setTimeout(resolve, 2000, 'p3->three');
});
var p4 = new Promise((resolve, reject) => {setTimeout(resolve, 1000, 'p3->four');
});
var p5 = new Promise((resolve, reject) => {reject('p5->reject');
});Promise.allSettled([p1, p2, p3, p4, p5]).then(values => {console.log(values);
}, reason => {console.log(reason)
});
then [{status:'fulfilled',value:'p1->one'},{status:'fulfilled',value:'p2->two'},{status:'fulfilled',value:'p3->three'},{status:'fulfilled',value:'p4->four'},{status:'rejected',value:'p5->reject'}]
一旦所指定的 promises 集合中每一個 promise 已經完成,無論是成功的達成或被拒絕,未決議的 Promise將被異步完成。那時,所返回的 promise 的處理器將傳入一個數組作為輸入,該數組包含原始 promises 集中每個 promise 的結果。
對于每個結果對象,都有一個 status 字符串。如果它的值為 fulfilled,則結果對象上存在一個 value 。如果值為 rejected,則存在一個 reason 。value(或 reason )反映了每個 promise 決議(或拒絕)的值。
可以發現和all相比,allSettled在其中一個promise返回錯誤時還可以繼續等待結果。并且不管內部的計時器定時多少毫秒,它都會等所有結果返回后按照傳參傳入的順序返回promise結果。
四、總結
根據不同場景選擇 Promise.all、Promise.race、Promise.allSettled 和 Promise.any 四個方法合適的使用。