js async/await


一、async

帶async關鍵字的函數,是聲明異步函數,返回值是promise對象,如果async關鍵字函數返回的不是promise,會自動用Promise.resolve()包裝。

async function test() {
    return 'test'
}
test();

返回值為 Promise {<resolved>: "test"}。

二、await

await等待右側表達式的結果,這個結果是promise對象或者其他值。
如果它等到的不是一個 promise 對象,那 await 表達式的運算結果就是它等到的東西。
如果它等到的是一個 promise 對象,await 就忙起來了,它會阻塞后面的代碼,等着 promise 對象 resolve,然后得到 resolve 的值,作為 await 表達式的運算結果。

function test() {
    return new Promise(resolve => {
        setTimeout(() => resolve("test"), 2000);
    });
}

const result = await test();
console.log(result);
console.log('end')

由於test()造成的阻塞,console.log('end')會等到兩秒后執行

所以為了避免造成阻塞,await 必須用在 async 函數中,async 函數調用不會造成阻塞。

function test() {
    return new Promise(resolve => {
        setTimeout(() => resolve("test"), 2000);
    });
}

async function test2() {
    const result = await test();
    console.log(result);
}
test2();
console.log('end');

先執行console.log('end'),兩秒后執行console.log('test')

如果await用在普通函數中,會報錯,如下:

三、async/await的執行順序

遇到await會阻塞后面的代碼,先執行async外面的同步代碼,同步代碼執行完,再回到async內部,繼續執行await后面的代碼。以下面的代碼分析:

        async function test1() {
            console.log('start test1');
            console.log(await test2());
            console.log('end test1');
        }
        async function test2() {
            console.log('test2');
            return await 'return test2 value'
        }
        test1();
        console.log('start async');
        setTimeout(() => {
            console.log('setTimeout');
        }, 0);
        new Promise((resolve, reject) => {
            console.log('promise1');
            resolve();
        }).then(() => {
            console.log('promise2');
        });
        console.log('end async');

執行的結果

· 首先執行宏任務,執行test1函數,執行console.log('statr test1')

· 遇到await,先執行右邊test2中的console.log('test2'),中斷了后面的代碼,執行test1外面的同步代碼

· 執行console.log('start async');

· 遇到setTimeout,推到到下個宏任務隊列中

· 執行Promise里面的同步代碼console.log('promise1')

· 運行到promise().then,發現是promise對象,推到微任務隊列中

· 執行console.log('end async')

· test1外面的同步代碼執行結束后,回到test1中,console.log(await test2())執行完成后返回Promise {<resolved>: "return test2 value"},是promise對象,推到微任務隊列中

· 此時第一個宏任務結束,執行所有的微任務,因為微任務隊列先進先出,所以先執行console.log('promise2'),后執行console.log('return test2 value')

· 執行test2完成后,后面的代碼不再阻塞,執行console.log('end test1');

· 執行下個宏任務,即執行console.log('setTimeout');

補充下有關宏任務和微任務的知識

宏任務和微任務都是隊列,宏任務有script、setTimeout、setInterval等,微任務有Promise.then catch finally、process.nextTick等,宏任務和微任務的關系如下:

先執行第一個宏任務,執行結束后,執行所有的微任務,然后執行下個宏任務。

四、async/await的優缺點

1. 優點

相對於promise,async/await處理 then 的調用鏈,代碼要清晰很多,幾乎和同步代碼一樣

2. 缺點

濫用 await 可能會導致性能問題,因為 await 會阻塞代碼

五、處理reject

1. try/catch

        async function fn() {
            try {
                await new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject('err3');
                }, 1000);
            })
            } catch (err){
                alert(err)
            }
        }
        fn()

2. catch

       async function fn() {
            await new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject('err');
                }, 1000);
            })
        }
        fn().catch(alert)

 

 

 

參考:

1. https://segmentfault.com/a/1190000007535316

2. https://segmentfault.com/a/1190000017224799

3. https://www.cnblogs.com/wangziye/p/9566454.html


免責聲明!

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



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