同期異步系列文章推薦
談一談javascript異步
javascript異步中的回調
javascript異步與promise
javascript異步之Promise.resolve()、Promise.reject()
javascript異步之Promise then和catch
javascript異步之async(一)
javascript異步之async(二)
javascript異步實戰
javascript異步總結歸檔
今天我們繼續討論promise
網絡上關於PromiseAPI使用的文章多如牛毛,爲了保持javascript異步系列文章的完整性,現在對promise的API進行簡單全面的介紹
準備工作
我在easy-mock添加了三個接口,備用
依然使用axios進行ajax請求
Promise.all()
Promise.all()有點像“並行”
我們看一個栗子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>promise</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
{
const p1 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1')
.then(({
data
}) => {
console.log('p1成功啦');
return data.data
})
const p2 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise2')
.then(({
data
}) => {
console.log('p2成功啦');
return data.data
})
const p3 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock')
.then(({
data
}) => {
console.log('p3成功啦');
return data.data
})
const p = Promise.all([p3, p1, p2])
.then(arr => {
console.log(arr);
console.log('Promise.all成功啦');
})
.catch(err=>{
console.log(err,'Promise.all錯啦');
})
}
</script>
</body>
</html>
我們知道axios返回的是一個promise對象,我們可以看下
console.log(p1);
Promise.all就是用於將多個 Promise 實例,包裝成一個新的 Promise 實例
Promise.all,接收一個數組作爲參數,數組的每一項都返回Promise實例
我們重點看這段代碼
const p = Promise.all([p3, p1, p2])
.then(arr => {
console.log(arr);
console.log('Promise.all成功啦');
})
.catch(err=>{
console.log(err,'Promise.all錯啦');
})
p1,p2,p3都是返回promise實例,Promise.all不關心他們的執行順序,如果他們都返回成功的狀態,Promise.all則返回成功的狀態,輸出一個數組,是這三個p1,p2,p3的返回值,數組的順序和他們的執行順序無關,和他們作爲參數排列的順序有關
我們看下輸出
爲了是拉長接口三的返回時間我對接口三的數據進行了修改,返回值是長度1000-2000之間的隨機數組,所以p3的執行要晚於p1和p2,
但我們輸出的arr,p3依然在前面,這給我們帶來一個便利,返回值數組的順序和方法的執行順序無關,可以進行人爲進行控制
我們將p1做一下改動,使p1報錯
const p1 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1')
.then(({
data
}) => {
console.log('p1成功啦');
return xxxx.data//將data.data修改爲xxxx.data
})
如果有一個返回失敗(reject),Promise.all則返回失敗(reject)的狀態,此時第一個被reject的實例的返回值,會傳遞給P的回調函數。
三個promise實例參數之間是“與”的關係,全部成功,Promise.all就返回成功,有一個失敗,Promise.all就返回失敗
換個角度說,一個promise的執行結果依賴於另外幾個promise的執行結果,
例如:
幾個ajax全部執行完了,才能渲染頁面,
幾個ajax全部執行完了,才能做一些數據的計算操作,
不關心執行順序,只關心集體的執行結果
Promise.race()
Promise中的競態,用法和Promise.all類似,對應參數的要求和Promise.all相同,傳入一個數組作爲參數,參數要返回一個Promise實例
race就是競爭的意思,數組內的Promise實例,誰執行的快,就返回誰的執行結果,不管是成功還是失敗
const p = Promise.race([p3, p1, p2])
.then(res => {
console.log(res);
console.log('Promise.all成功啦');
})
.catch(err=>{
console.log(err,'Promise.all錯啦');
})
通過輸出我們發現
p1是第一個完成的,所以p的返回結果就是p1的執行結果
而且就算完成,但是 進程不會立即停止,還會繼續執行下去。
關於race的使用場景
搜了一下,很多文章都說是用來解決網絡超時的提示,類似於下面這樣
const p3 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock')
.then(({
data
}) => {
console.log('p3成功啦');
return data.data
})
const p4 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('網絡連接超時')), 50)
})
const p = Promise.race([p3, p4])
.then(res => console.log(res))
.catch(err => console.log(err));
p3的ajax和50ms的定時器比較,看誰執行的快,如果超過了50ms,p3的ajax還沒返回,就告知用戶網絡連接超時
這裏有個問題,就算提示超時了,p3還在繼續執行,它並沒有停下來,直到有狀態返回
個人觀點:race可以用來爲ajax請求的時長劃定範圍,如果ajax請求時長超過xxxms會執行某個方法,或者ajax請求時長不超過xxms會執行某個方法,總之,race的應用空間不是很大
Promise.finally()
finally方法用於指定不管 Promise 對象最後狀態如何,都會執行的操作。該方法是 ES2018 引入標準的。
const p = Promise.race([p3, p4])
.then(res => console.log(res))
.catch(err => console.log(err))
.finally(() => {
console.log("finally的執行與狀態無關")
});
當promise得到狀態(不論成功或失敗)後就會執行finally,