同期異步系列文章推薦
談一談javascript異步
javascript異步中的回調
javascript異步與promise
javascript異步之Promise.resolve()、Promise.reject()
javascript異步之Promise then和catch
javascript異步之async(一)
javascript異步之async(二)
javascript異步實戰
javascript異步總結歸檔javascript
今天咱們繼續討論promise
網絡上關於PromiseAPI使用的文章多如牛毛,爲了保持javascript異步系列文章的完整性,如今對promise的API進行簡單全面的介紹html
我在easy-mock添加了三個接口,備用
依然使用axios進行ajax請求java
Promise.all()有點像「並行」
咱們看一個栗子ios
<!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對象,咱們能夠看下es6
console.log(p1);
Promise.all就是用於將多個 Promise 實例,包裝成一個新的 Promise 實例
Promise.all,接收一個數組做爲參數,數組的每一項都返回Promise實例
咱們重點看這段代碼ajax
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報錯axios
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中的競態,用法和Promise.all相似,對應參數的要求和Promise.all相同,傳入一個數組做爲參數,參數要返回一個Promise實例
race就是競爭的意思,數組內的Promise實例,誰執行的快,就返回誰的執行結果,無論是成功仍是失敗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的執行結果
並且就算完成,可是 進程不會當即中止,還會繼續執行下去。網絡
搜了一下,不少文章都說是用來解決網絡超時的提示,相似於下面這樣
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的應用空間不是很大
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,