Noder eyes for frontend guys

827 views

Published on

my s

Published in: Technology
1 Comment
3 Likes
Statistics
Notes
No Downloads
Views
Total views
827
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
11
Comments
1
Likes
3
Embeds 0
No embeds

No notes for slide

Noder eyes for frontend guys

  1. 1. Noder eyes for frontend guys by Fillano
  2. 2. 先說聲抱歉 Orz
  3. 3. 關於題目● 源自 "Queer eyes for straight guys"● 澄清一下 ○ 寫node.js不表示比較厲害,只是希望能讓熟悉瀏覽器 的Javascript coder可以知道進入node.js需要的知識跟 常見的難點 ○ Im not queer, but I do have some friends.● 另外...
  4. 4. 這個投影片不會講到● node.js的教學● 各個module怎麼用的詳細說明● 怎麼做出XXX(忍不住還是會...)
  5. 5. 這個投影片會專注在● 寫node.js程式需要的關鍵知識● 如何開始寫node.js程式的一些提示
  6. 6. 開始吧...
  7. 7. window物件在哪?● 可能情境:裝完node.js,進入shell,不知道有什 麼可以使用● 在瀏覽器中,一切都可以從window物件開始, 那在node.js中,有什麼相同的東西?● 這要從Javascript的基本特性談起...
  8. 8. Javascrip基本:依賴於host環境● 核心物件之外,所有能用的功能,都放在Global 中● 在browser中,Global就是window物件● 在node.js中,Global就是global物件● 檢查一下:test001.js● 有三個同名的物件,實際上都是global物件● 檢查一下:test001a.js● 但是呢...
  9. 9. node.js對於Global做了一點調整● 操作global物件,可以反應在global scope● 但是直接操作global scope,並不會影響到 global物件● 這跟在瀏覽器環境中的行為不太一樣● 檢查一下:test001b.js● 在瀏覽器中:test794.html● 那麼...
  10. 10. global物件到底能做什麼● 只有: ○ 操作TypedArray需要的相關物件 ○ process物件 ○ Buffer constructor ○ setTimeout/setInterval相關函數 ○ console物件,用來作stdio● 檢查一下:test002.js● 接下來咧?好像沒啥東西...
  11. 11. 那其他功能怎麼辦?● 其實還有require這個核心函數,可以用它來載 入模組● 檢查一下:test003.js● 後面還會詳細解釋一下模組的運作● 了解了global物件,再看一個偶爾會有人問的 問題...
  12. 12. 我可以使用jQuery嗎?● 通常我會想:別傻了,你在寫伺服器程式● 不是沒有解(JSDom...)● 但除了做蜘蛛,通常不會用到● 下一個問題也有不少人問...就是...
  13. 13. 什麼?單一執行緒?● 用關鍵字應該可以找到不少這方面的討論● 不過這個問題說來話長...下一頁繼續
  14. 14. 其實,single thread是寫Javascript的必備知識● 參考 ○ Resig: How JavaScript Timers Work ○ Zakas: Professional Javascript for Web Developers: p. 598 Advanced Timers ○ Opera: Timing and Synchronization in Javascript ○ HTML5: HTML5 Spec - 6.1.4 Event loops ○ YDN: Understanding event loops and writing great code for Node.js
  15. 15. 歸納起來,就是● 不論是非同步的事件、timer、UI parsing等● browser所載入的每個網頁,你寫的Javascript 都是在一個thread裡面跑● 在node.js也是這樣
  16. 16. 所以,Javascript到底怎麼跑?● 可以把Javascript的執行過程想像成 a. 執行top most的程式碼(主要是global scope,以及此時 執行的函數) b. 進入event loop c. 一有有事件程式放進event queue,event loop就會取出 來執行 ■ 由timer觸發的,不會在時間到之前執行,但是可能 會更慢 ■ 由event觸發的,就是儘快執行● node.js的特異功能 a. process.nextTick():會盡量排在event queue前面讓他 可以先執行,而不是從後面填入
  17. 17. 這不是例外,但其實你有機會碰到別的thread● 在網頁端: ○ frame/iframe ○ web worker● 在node.js ○ sub process ○ threads-a-gogo模組(這是真的thread,只能透過 message溝通,目前還無法做什麼事)● 測試:test644.html(WebWorker的global跟網頁中完全不同)
  18. 18. 在底層,還有更多東西必須使用thread● 寫Javascript不會直接接觸...但是在機制上 ○ 瀏覽器:XMLHttpRequest底層 ■ onreadystatuschange ● 網路I/O在另外一個thread跑,根據處理的狀態 變化,才把叫onreadystatuschange事件處理函 數塞進event queue ○ node.js:I/O底層 ■ fs.read ■ fs.write● 所以,single thread是對Javascript Coder必須的概念,但是 引擎實作並不是這樣
  19. 19. single thread的方便性● 同一時間不會執行兩段程式 ○ 沒有race ○ 不需要lock ○ 寫非同步比較簡單● 但是我們寫的code可能會...
  20. 20. 程式寫壞了,就全部塞住● 這不論在瀏覽器或伺服器端都一樣,某個 function中的程式卡住(ex. 無窮迴圈),就全部 卡住了● 在node.js,沒有catch到的exception,會讓程式 exit,但是沒exception照樣可能卡著(ex. 無窮 迴圈)● 就算沒卡住...
  21. 21. 程式寫不好,伺服器反應就全部變慢● 沒那麼糟,但是不優● 但是有時...就是得做花時間的事情● 有什麼辦法?
  22. 22. 所以有些事可以慢點做● 程式打死結(ex. 無窮迴圈),是一定沒救● 但是某個事件處理程式跑太久,還是會阻礙別 人● 在Browser跟node.js解法都一樣,make it async by do something later● 使用setTimeout()/setInterval()● 使用process.nextTick()● 在single thread中跑的程式,就像DOS時代的合 作式多工...
  23. 23. 不過async會讓邏輯更複雜XD● 這在node.js常碰到,建議要習慣用async的邏 輯來思考事情● 有一些解決方法,容後再述● 另外的問題是,程式都在同一個thread跑喔, 可是...
  24. 24. node.js在伺服器端執行耶!?● 這不是瀏覽器...● 如果只有單核心,再多thread也只會用到一個 cpu核心的資源,就沒差● 可是,我的伺服器有四路八核心cpu,總共有32 核心,但是node只會用到一個...● 解法在v0.6.x之後出現...容後再敘● 有了一些基本認識,可以開始coding了...不過一 頭鑽進去會發現...
  25. 25. hello world...然後我要做什麼?● hello world總是很美好XD● 但是很遺憾...http模組幫你做的事情不多● 因為他沒做,所以你需要基本的http知識 ○ http request ○ http headers ○ session相關 ■ cookie header ■ setcookie header ■ 怎麼做出伺服器端session ○ MIME ○ ...● 另外,沒人幫你map靜態檔案● ...
  26. 26. 對於新手來說,單靠node.js核心模組是不可能寫出功能完整的伺服器Orz● 想像一下,你要用幾個基本的物件做出apache httpd伺服器,工程很大的...● 我自己為例,之前參加ITHelp鐵人賽,花了一 個月還只有架構● 所以要快的話,還是得先靠第三方模組 ○ Connect middleware可以做基礎 ○ 一些Web Framework ■ Express ■ others ● Meteor ● Mojito ● ...● 那要怎樣找模組?...
  27. 27. 模組管理工具:NPM● NPM(Node Package Manager)● 原本是第三方的解決方案● 目前已納入node.js的binary distribution中● 怎麼找模組? ○ `npm search KEYWORD` (常會用完記憶體) ○ http://search.npmjs.org/ (官網,但是很慢) ○ https://github. com/joyent/node/wiki/modules (這是分門別類的目 錄,但是更新可能比較慢) ○ nipster (很快,而且用評分排序)
  28. 28. node怎麼找到模組● 之前測試過...test003.js可以看到一些線索● 模組預設搜尋路徑 ○ 目前工作目錄下的node_modules目錄 ○ require.main.paths陣列中的目錄● npm list -g顯示的路徑加上node_modules ○ 預設 ■ UNIX: /usr/lib or /usr/local/lib ■ Windows: %APPDATAnpm● 用npm安裝/管理模組會使用的路徑 ○ 沒有加-g:目前路徑 ○ 有加-g:npm list -g顯示的路徑
  29. 29. 想使用global module● 如果(不建議)希望可以直接使用● 需要設定NODE_PATH環境變數,指向npm list -g使用的模組目錄 + node_modules
  30. 30. 使用了模組...怎麼維護相依性?● 我們使用npm,npm使用package.json檔● package.json(模組根目錄中) ○ 不管寫不寫模組,最好都知道裡面定義的各個欄位 ○ 跟執行相關 ■ 定義模組的entry檔案 ■ 定義模組的相依性● 許多node.js hosting service,都支援package. json,在deploy的過程中,會幫你把相依的模組 裝好● 參考: ○ http://package.json.nodejitsu.com/ ○ npm help json
  31. 31. node.js的模組載入機制與注意事項● require是同步執行的 ○ 呼叫require時,要等到模組載入完畢,才會執行下一行 程式● module是在沙箱中跑的 ○ 所以,模組裡面沒有辦法動到主程式 ○ 主程式要用到的東西,全部都要export(module.exports 或exports)● 執行過一次require後,模組就會被cache起來 ○ 所以,修改過的module,要重新啟動程式才會有作用
  32. 32. 但是我希望程式可以在修改後不停機自動apply耶...● 最好讓host服務替你做,省功夫● 手動做的話,可以考慮使用cluster● 驗證一下:test005.js ○ 由於每個worker都是獨立的process,kill掉再重新執 行,就會使用新的程式了 ○ 缺點是:master無法更新... ○ 仔細想一想:如果把worker內的程式寫成模組來載入, 然後master用fs.watch模組的目錄,然後每次deploy 都更新這個模組...其實就類似hosting的做法了
  33. 33. 但是,我需要AMD的話怎麼辦?● 參考:require.js● 其實,你可以自己做● 例如:node-amd-loader● 重點: ○ node只提供了核心模組 ○ 沒人告訴你其他的不能自己做 ○ 忘記那些爭論吧(阿?有爭論?)
  34. 34. 我需要物件導向嗎?● node.js常用的作法: ○ 使用util.inherits(),這是給constructor來用的喔 ○ 最常使用的地方:需要使用到事件機制,就要繼承 EventEmitter● 其他...就任意...Javascript有多種作法● 參考一下良葛格的意見 ○ 程式語言的特性本質(三)-從消弭重複性看封裝、繼 承、多型● 再來是另一個常被問到的問題...
  35. 35. 有辦法避開callback地獄嗎?● 這是無法避免的,請練習async的邏輯思考● 可以透過適當的調整來改善 ○ 取代匿名函數callback(這是一個過程,這樣還可以方 便單元測試) ■ 改用非匿名的函數 ■ 進一步利用模組帶入這個函數 ○ 利用flow control來管理函數,讓你可以控制數個函數 執行過程的關係,例如某幾個函數要順序執行、某幾個 函數要平行執行等
  36. 36. 有辦法避開非同步地獄嗎?● 同樣難以避免● 而且,在執行上有時會碰到邏輯上的困難點● 解決方式如前述● 那麼...
  37. 37. 什麼是flow control?● 函數在Javascript是一等公民,所以可以用函 數來處理函數● 測試一下:test006.js ○ 執行三個函數 ○ 全部執行完畢,才執行某個函數來處理結果● 除了使用flow control,要能使用flow control的 函數,通常要改寫成cps的形式● cps (continuation passing style) ○ 簡單地說就是傳入一個callback ○ 在函數結束時(可能不只一處),呼叫這個callback,有 返回值時,需要把返回值傳給它
  38. 38. 關於flow control的好文章● Tim Caswell ○ Control Flow in Node ○ Control Flow in Node Part II ○ Control Flow in Node Part III● Mixus tech blog ○ Essential Node.js patterns and snippets ○ 我的例子用這個改的,因為邏輯最簡單● 一些模組 ○ https://github.com/creationix/step ○ https://github.com/caolan/async ○ https://github.com/laverdet/node-fibers
  39. 39. 另外一個讓程式碼更有結構又乾淨的方式● CoffeeScript● ...我沒在用,我已經太習慣Javascript了XD● 早上有人講這個喔(高見龍 / 龍哥)● 另外一個寫伺服器會發現的,是關於...
  40. 40. gloal variables● 以http server為例,每個request是一個事件● 要維護cross request的狀態(ex. session),用 global variable就可以做到(其實不一定,要看 事件處理函數定義的位置)● 不過當需要scale的時候,這個作法就會出問題 (ex. cluster)● 所以,共享的狀態,儘量用外部實現比較好 (memcache, mongodb etc.)● 好,終於要來看怎麼解決無法利用多核心cpu 的...
  41. 41. cluster模組● since v0.6.x● 解決single thread無法充分利用多核心的系統 優勢的問題● 使用多個sub process,共享同一個port● master/worker之間,透過message來溝通● 測試一下?(之前測過了XD)
  42. 42. cluster不是真的scaling● 不要被cluster這個名字拐了● 真正要scaling,請使用reverse proxy,例如: ○ nginx ○ node-proxy模組 (效能不如nginx)● 基本上,不論使用怎樣的程式語言,大多數伺 服器都可以這樣scale● 另外,許多PAAS(node.js hosting)會提供方案及 工具來做
  43. 43. 我要怎樣debug?● 建議把邏輯集中到function,放進module,做單 元測試(這是基本的refactoring)● 簡單的邏輯bug,用console.log、console.dir就可 以解決● 如果需要做profiling、找出memory leak,再來使 用debug工具,例如 ○ Using Eclipse as Node Applications Debugger ○ other solutions: node-inpector, ndb etc.
  44. 44. 有什麼hosting服務嗎?● 有許多廠商提供這方面的服務 ○ Joyent (MiCloud) ○ Heroku ○ Nodejitsu ○ Nodester ○ Azure ○ more...● 選擇重點 ○ 基本管理工具 ○ deploy方式 ○ 擴充方案
  45. 45. 兩三事代替總結● 這些主題,有很多是在nodejs group上常見的● 而且,裡面有些東西是火藥庫● node.js開發team的目標,是一個精簡而可靠 的核心,所以會放棄很多用第三方模組就可以 做到的功能● 有需求的地方,就是可以自己插手的地方,畢 竟node.js還很年輕● 後面某一場,Ben會分享他為什麼要開發自己 的framework,大家可以聽一聽他的心得
  46. 46. Q&A
  47. 47. 我最近的出沒地點● 我的Facebook● 我的噗浪● facebook Javascript.tw group● facebook nodejs.tw group● facebook PHP 台灣 group● Zen of Friends讀書會以及Web Dev Party● 我的部落格 (自從用噗浪以後就少出沒了)● 歡迎來交朋友...
  48. 48. The End

×