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


ES6 提供的 Promise 方法和 ES7 提供的 Async/Await 語法糖都可以更好解決多層回調問題, 詳細用法可參考:https://www.cnblogs.com/cckui/p/9915604.html,下面進一步介紹 promise 和 async/await 用法的異同。

首先定義以下三個異步函數:

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

最終打印結果:

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 中。

某些情況下,如果上面sleep3000、sleep200、sleep4000分別代表頁面不同模塊的加載時間,在頁面剛打開時,需要當所有模塊加載完成后,清除loading。此時可以作如下處理:

console.log('Now:', new Date());

Promise.all([
    sleep2000(),
    sleep3000(),
    sleep4000()
]).then((res) => {
    console.log(res)
})

最終打印結果:

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就會解決或拒絕。

console.log('Now:', new Date());

Promise.race([
    sleep2000(),
    sleep3000(),
    sleep4000()
]).then((res) => {
    console.log(res)
})

因為 sleep2000 最先執行完成,所以在2秒后,就會立即進入then。

最終打印結果:

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(), 各個異步是有序的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM