async&await

JavaScript中異步從來都不簡單,很長一段時間內, 我們都是使用的回調來實現。後來,我們可以使用promise,現在,我們可以使用asyncawait(以下簡稱異步函數)來實現異步。

雖然異步函數的出現使得編寫異步函數更加容易了,但是同樣也存在陷阱,並且對於初學者並不是那麼的友好。

在這篇文章的兩個部分中,我將和你們一起分享一切你需要知道的關於異步函數的知識。

Asynchronous functions

異步函數包含async關鍵字,你可以像普通的函數聲明一樣使用它:

    async function functionName (arguments) {
        //Do something asynchronous
    }

你也可以使用箭頭函數

    const functionName = async (arguments) => {
        //Do something asynchronous
    }

Asynchronous functions always return promise

返回什麼值並不重要,使用異步函數返回的值總是一個promise

    const getOne = async _ => {
        return 1;
    }

    const promise = getOne();
    console.log(promise) // Promise

await關鍵詞

當你調用一個promise時,你使用then來進行下一步,就像這樣:

    const getOne = async _ => {
        return 1;
    }

    getOne()
        .then(value => {
            console.log(value); // 1
        })

await關鍵詞讓你定義reslove函數,一旦promise成功了,它就會返回傳遞到then函數的參數。

    const test = async _ => {
        const one = await getOne();
        console.log(one);
    }

    test();

Return await

在返回一個promise之前,等待是沒有必要的,你可以直接返回promise.

如果你返回一個await, 你先實現了原來的promise,然後,你又創建一個新的promise,return await雖然不影響什麼,但是沒有必要多此一舉。

    //Don't need to do this
    const test = async _ => {
        return await getOne();
    }

    test()
        .then(value => {
            console.log(value); // 1
        })

    //Do this instead
    const test = aysnc _ => {
        return getOne();
    }

    test()
        .then(value => {
            console.log(value); //1
        })

注意,如果你不需要await,你不許要使用異步函數。上面的列子可重寫。

    //Do this instead
    const test = _ => {
        return getOne();
    }

    test()
        .then(value => {
            console.log(value); // 1
        });

Handling errors

如果一個promise導致了錯誤,你可以使用catch來捕捉他

    const getOne = aysnc (success = true) => {
        if (success) return 1;
        throw new Error('failure');
    }

    getOne(false) 
        .then(error => console.log(error)); // failure

如果你想在異步函數中處理錯誤,你需要使用一個try/catch來捕捉它。

    const test = async _ => {
        try {
            const one = await getOne(false);
        }catch (e) {
            console.log(e); //failure
        }
    }

    test();

如果你有多個await關鍵詞,這樣寫錯誤處理會變的很醜

    const test = async _ => {
        try {
            const one = await getOne(false);
        }catch (e) {
            console.log(e); //failure
        }

        try {
            const two = await getTwo(false);
        }catch (e) {
            console.log(e); //failure
        }

        try {
            const three = await getThree(false);
        }catch (e) {
            console.log(e); //failure
        }
    }

    test();

但是還有一個更好的辦法。

我們知道異步函數總是返回一個promise,當我們調用一個promise,我們在catch中處理錯誤。這意味這我們可以通過添加catch來處理錯誤。

    const test = async _ => {
        const one = await getOne(false);
        const two = await getTwo(false);
        const three = await getThree(false);
    }

    test()
        .catch(error => console.log(error));

注意: Promise方法只會讓你捕捉一個錯誤。

Multiple awaits

await會阻塞js執行下一行代碼,知道promiseresolve被執行完成。這可能會降低執行的效率。

我們需要創建一個延遲來在實際中演示,通過sleep來創建延遲。

    const sleep = ms => {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    //Using Sleep
    console.log('Now');
    sleep(1000)
        .then(value => console.log('after one second')); // print 'now' immediately, 'after one second' printed in console after 1 second

現在我們來看需要等三個promise的情況,每一個promise都有一個一秒的延遲。

    const getOne = _ => {
        return sleep(1000).then(val => 1)
    }

    const getTwo = _ => {
        return sleep(1000).then(val => 1)
    }

    const getThree = _ => {
        return sleep(1000).then(val => 1)
    }

如果你await這些promises在一行中,你將不得不等待3秒在那些promise全部結束之前。這不是很好因爲我們強迫JavaScript等待額外的2秒在做我們需要的之前。

    const test = async _ => {
        const one = await getOne();
        console.log(one);

        const two = await getTwo();
        console.log(two);

        const three = await getThree();
        console.log(three);

        console.log('Done');
    }

    test(); //Console shows ‘Now’ immediately. One second later, it shows 1. Another second later, it shows 2. Another second later, it shows 3 and ‘Done’ at the same time.

如果getOne, getTwo, getThree可以同時(simultraneously)執行,你可以節省兩秒。你可以使用promise.all同時執行三個promise.

    const test = async _ => {
        const promise = [getOne(), getTwo(), getThree()];
        console.log('Now');

        const [one, two, three] = await Promise.all(promise);
        console.log(one);
        console.log(two);
        console.log(three);

        console.log('Done');
    };

Console shows ‘Now’ immediately. After one second, console shows 1, 2, 3, and ‘Done’

歡迎補充。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章