2015年12月16日 星期三

[Node.js] 初學 Node.js 注意這三點,會比較好上手

1. 同步和非同步執行順序抽像想像


node.js 是 single thread 所以不會有並行
所以 sync 部份跑完才會開始跑 async 或是在 even driven 才跑 async 有點像下圖



async 部份是看誰先排進 async query 內誰先優先執行
所以像
var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

async_function(1, function(val) {
    console.log(val);
    async_function(2, function(val) {
        console.log(val);
        async_function(3, function(val) {
            console.log(val);
        });
    });
});

console.log(100);
會列出
100
1
2
3
所以在同一個 async scope 會保證其順序性 1 > 2 > 3

再看一個範例,在 sync 等地方再加一個不同的 async scope
var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

async_function(1, function(val) {
    console.log(val);
    async_function(2, function(val) {
        console.log(val);
        async_function(3, function(val) {
            console.log(val);
        });
    });
});

console.log(100);

async_function(4, function(val) {
    console.log(val);
    async_function(5, function(val) {
        console.log(val);
        async_function(6, function(val) {
            console.log(val);
        });
    });
});
會列出
100
1
4
2
5
3
6
一樣在同一個 async scope 會保證其順序性
1 > 2 > 3
4 > 5 > 6
但不同 scope 會形成交叉,因為在 sync 的 scope 時 1>4 是這順序排進 queue
而印 1 後,2 被排進 queue 內,4 被執行
4印出後,5排進 queue 內,2被執行,以此類堆

推薦可以看下面這篇,會更清楚為什麼會這樣,雖然主要在講為什麼 async 會比較快,但圖片說明很棒,淺顯易懂
http://blogger.gtwang.org/2014/02/node-js-is-faster-than-java-for-concurrent-data-processing-operations.html

另外這篇在講 node.js 的 process queue
http://fred-zone.blogspot.tw/2012/03/nodejs.html


2. 區分是 sync 的 function 還是 async 的 function


這點 JSDC 2015 Jonathan 也有提到
http://www.jongleberry.com/async-control-flow/assets/player/KeynoteDHTMLPlayer.html#8

大部份只要有 callback 幾乎都是 async 的 function
除了 array iteration methods 操作,像 forEach、map...等
(Ref:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Iteration_methods)

另外很多 function 如果結尾有 sync 就是同步版的 function
像 fs 內就有,例如 fs.open 是 async 的版本 fs.openSync 就是 sync 的版本


3. Control Flow (俗稱 callback hell)


因為 callback 的方式導致閱讀程式變成很難
而且很多整理程式的方法,都不太適用,例如 design pattern

目前常聽到的解決是使用這三個方法來解:aync、promise、async/await

aync:
https://github.com/caolan/async
我個人目前都是用這個
比較常用的像有 waterfall

promise:
這裡指的是 ES6 的 promise
不過我也還沒研究:D
npm 有一些類似的 modules

async/await:
這裡指的是 ES7 的
npm 也有幾個,但都會降低效能
https://github.com/yortus/asyncawait#5-performance
像這個會降 20%左右

不過另一個經驗在大部份的 refactory 書(像易讀程式之美學)都有提到。
儘量把程式 function 化,讓 function 和 method 只做一件事,即使在 callback hell 中,也能讓程式變的比較好讀。




題外話
http://www.jongleberry.com/async-control-flow/assets/player/KeynoteDHTMLPlayer.html#12
有提到儘量使用 thrown new Error("boom") 取代 thrown "boom"
這樣才有 stack trace 能看

Reference:
http://blogger.gtwang.org/2014/02/node-js-is-faster-than-java-for-concurrent-data-processing-operations.html
http://fred-zone.blogspot.tw/2012/03/nodejs.html
http://www.jongleberry.com/async-control-flow/assets/player/KeynoteDHTMLPlayer.html#8
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Iteration_methods
https://github.com/caolan/async
https://github.com/yortus/asyncawait#5-performance

沒有留言:

張貼留言