2018/03/22

Async Await

ndoe.js 預設的功能都是非同步的,一般來說程式語言都是依序從上執行到下,而 node.js 的話不是,我們來看一下一個簡單的範例

const runTimeout = () => {
    setTimeout(() => {
        console.log('time is up');
    }, 2000);
};

runTimeout();
console.log('done');

以往我們的想像會是先拿到 time is up 在拿到 done,但這個 case 的執行結果會先拿到 done 再拿到 time is up,這樣的優點是你可以一次同時處理很多事情,拿到結果後進行下一步,之前要達到這樣的效果,要寫很多程式碼,然而現實生活中其實大多的功能都必須依序執行,所以有了 promise 來解決這件事情,網路上範例很多,我這邊會用最精簡的作法當作是個人的筆記。

以上方例子來說,修改方式如下:

const runTimeout = async (time) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(time);
        }, time);
    });
};

const main = async () => {
    try {
        const r1 = await runTimeout(2000);
        const r2 = await runTimeout(1000);

        console.log(r1);
        console.log(r2);
        console.log('done');
    } catch (e) {
        console.error(e);
    }
};

main();

我將程式買改寫成可帶入參數,這樣可以驗證他的確是依序做完的,執行結果為:

2000
1000
done

另一個情境是,執行數量是動態的話要怎麼實現,範例如下:

const runTimeout = async (time) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(time);
        }, time);
    });
};

const times = [
    3000,
    1000,
    2000
];

const main = async () => {
    try {
        Promise.all(times.map(runTimeout)).then((msg) => {
            console.log(msg);
            console.log('done');
        });
    } catch (e) {
        console.error(e);
    }
};

main();

執行結果:

[ 3000, 1000, 2000 ]
done

第二種作法:

const runTimeout = async (time, name) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`run ${name} in ${time} secs`);
        }, time);
    });
};

const times = [
    [3000, 'a'],
    [1000, 'b'],
    [2000, 'c']
];
const runners = times.map(async (item) => {
    const result = await runTimeout(item[0], item[1]);

    return result;
});
const main = async () => {
    try {
        Promise.all(runners)
            .then((msg) => {
                console.log(msg);
                console.log('done');
            });
    } catch (e) {
        console.error(e);
    }
};

main();

執行結果:

[ 'run a in 3000 secs',
  'run b in 1000 secs',
  'run c in 2000 secs' ]
done

沒有留言: