ES6 提供的 Promise 方法和 ES7 提供的 Async/Await 語法糖均可以更好解決多層回調問題, 詳細用法可參考:http://www.javashuo.com/article/p-rxlzxwpe-du.html,下面進一步介紹 promise 和 async/await 用法的異同。html
首先定義如下三個異步函數:數組
function sleep3000() { return new Promise(function (resolve, reject) { setTimeout(function () { console.log('sleep3000 執行完成'); resolve(new Date()); }, 3000); }) }; function sleep2000() { return new Promise(function (resolve, reject) { setTimeout(function () { console.log('sleep2000 執行完成'); resolve(new Date()); }, 2000); }) }; function sleep4000() { return new Promise(function (resolve, reject) { setTimeout(function () { console.log('sleep4000 執行完成'); resolve(new Date()); }, 4000); }) };
console.log('Now:', new Date()); sleep3000().then((d) => { console.log('3000:', d); }) sleep2000().then((d) => { console.log('2000:',d); }) sleep4000().then((d) => { console.log('2000:',d); })
最終打印結果:promise
Now: 2019-04-08T02:29:38.388Z sleep2000 執行完成 2000: 2019-04-08T02:29:40.398Z sleep3000 執行完成 3000: 2019-04-08T02:29:41.398Z sleep4000 執行完成 2000: 2019-04-08T02:29:42.394Z
promise.all()
方法Promise 的 all() 方法提供了並行執行異步操做的能力,即在全部異步操做執行完後才執行回調, all()裏面接收一個數組,數組中每一個元素都返回一個 promise 對象。異步
all()裏面的異步都執行完成後,纔會把每一個異步結果以數組的形式放入 then 中。async
某些狀況下,若是上面sleep3000、sleep200、sleep4000分別表明頁面不一樣模塊的加載時間,在頁面剛打開時,須要當全部模塊加載完成後,清除loading。此時能夠做以下處理:函數
console.log('Now:', new Date()); Promise.all([ sleep2000(), sleep3000(), sleep4000() ]).then((res) => { console.log(res) })
最終打印結果:ui
Now: 2019-04-08T02:43:07.139Z sleep2000 執行完成 sleep3000 執行完成 sleep4000 執行完成 [ 2019-04-08T02:43:09.144Z, 2019-04-08T02:43:10.145Z, 2019-04-08T02:43:11.144Z ]
promise.race()
方法Promise 的 race() 方法 與 all () 相反,即只以執行最快的那個promise爲準,一旦race()中的某個promise解決或拒絕,全部返回的 promise就會解決或拒絕。code
console.log('Now:', new Date()); Promise.race([ sleep2000(), sleep3000(), sleep4000() ]).then((res) => { console.log(res) })
由於 sleep2000 最早執行完成,因此在2秒後,就會當即進入then。htm
最終打印結果:對象
Now: 2019-04-08T02:44:34.193Z sleep2000 執行完成 2019-04-08T02:44:36.200Z sleep3000 執行完成 sleep4000 執行完成
注意:2秒進入 then 後, sleep3000 和 sleep4000 並無被中止, 仍會繼續走完,只是不會處理resolve或reject。
console.log('Now:', new Date()); async function getDate () { let res1 = await sleep3000(); let res2 = await sleep2000(); let res3 = await sleep4000(); console.log('3000:', res1); console.log('2000:', res2); console.log('4000:', res3); } getDate();
最終打印結果:
Now: 2019-04-08T02:58:23.990Z sleep3000 執行完成 sleep2000 執行完成 sleep4000 執行完成 3000: 2019-04-08T02:58:26.996Z 2000: 2019-04-08T02:58:29.001Z 4000: 2019-04-08T02:58:33.004Z
經過打印時間,可見,每處理完前一個await,纔會處理下一個await,上面全部處理完花費了9秒。
因此, 只有當處理後面await須要前一個await返回值時,才能夠用以上方法。
當三個異步相互之間沒有關係,須要同時發送時:
console.log('Now:', new Date()); async function getdate () { let res1 = sleep3000(); let res2 = sleep2000(); let res3 = sleep4000(); let res = await Promise.all([res1, res2, res3]); console.log(res); } getdate();
最終打印結果:
sleep2000 執行完成 sleep3000 執行完成 sleep4000 執行完成 [ 2019-04-08T03:11:24.280Z, 2019-04-08T03:11:23.280Z, 2019-04-08T03:11:25.275Z ]
對比 2 和 5 的打印結果,能夠看出,兩者打印的返回數組裏面的順序是有區別的: