異步操做之 Promise 和 Async await 用法進階

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);
    })
};

1. 使用 promise 方法分別執行以上三個函數

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

2. 使用 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 ]

3. 使用 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。

4. async/await 處理以上三個函數

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返回值時,才能夠用以上方法。

5. async/await 中使用 promise.all 並行處理異步操做

當三個異步相互之間沒有關係,須要同時發送時:

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 的打印結果,能夠看出,兩者打印的返回數組裏面的順序是有區別的:

  • 只用promise.all()時,各個異步是無序的;
  • 在 async/await 中使用 promise.all(), 各個異步是有序的。
相關文章
相關標籤/搜索