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
沒有留言:
張貼留言