譯者按:前不久Oreilly出了一本小冊子“What is Node?”,扼要的講解了Node的身世和所適用的場景,作者文筆輕松流暢、內容充實,是非常難得的學習資料。翻譯出來,和大家分享~
譯文全文:http://jayli.github.com/whatisnode/index.html
學習Node不是一件輕松事兒,但你所收到的回報是對得起你的付出的。因為當下Web應用開發中的諸多難題唯有JavaScript才能解決。
目錄
1,專家們的警告!
2,Node:幾個小例子
3,Node不是JavaScript,Node可以運行JavaScript
4,和Node服務器的交互
5,快速入門手冊
6,解釋器之惑
7,基於事件的Web應用
8,Node的用武之地
“你夠酷嗎?來用我吧!” Node.js 為最新潮的編程語言提供了一系列很酷的API和工具箱,它可以直接應用於傳統的Rails、Ajax、Hadoop、甚至可以某種程度上用於iPhone開發和HTML5。如果你參加過一些大型技術會議,你總是會聽到一些關於Node.js的主題演講,盡管這些話題對普通的開發者來說依然有些難以企及。
你可能已經聽說Node.js(有時我們將其簡稱為“Node”)是一個服務器端的解決方案,它可以運行JavaScript,並可以作為Web服務來處理HTTP請求。如果這些東東還不至於讓你暈頭轉向的話,轉眼間關於端口、sockets和線程的討論就又成了當下最熱門的話題,你會覺得這些東西讓你眼花缭亂。這些內容真的屬於JavaScript的范疇嗎?為什麼世界上那麼多人寧願將JavaScript脫離浏覽器而運行,更不用說將JavaScript運行於服務器端了?
好消息是,你所聽到的(所想到的)關於Node的一切都是正確的。Node的的確確是屬於網絡編程的范疇,用以處理服務器端的請求和響應。壞消息是和之前的Rails、Ajax和Hadoop一樣,真正實用的技術資料實在太少。等到基於Node的“優秀的”框架成熟之後,技術資料一定會跟得上的,但何必要等到技術書籍和教程都出來之後再去嘗試使用Node呢?現在就使用Node,說不定會給你的代碼帶來意想不到的改觀,甚至讓你的程序變得更易實現。
和大多數技術一樣,Node也是新瓶裝舊酒:它看起來不透明而且很怪異,但獨受小開發團隊的青睐。如果你沒有接觸過Node,則需要學習一些很容易上手的服務器端腳本。你需要化時間來搞清楚Node,因為即便是運行於服務器端的JavaScript,它和客戶端JavaScript也極為不同。實際情況是,你不得不自己給自己洗腦,以便重新學習理解圍繞JavaScript的事件處理機制、異步IO和一些網絡基礎知識。
不幸的是,這意味著如果你已經用Node作開發超過兩年時間的話,你會覺得這篇文章內容很單調乏而且過於簡單。你會開始尋找新的“刺激”,比如將Node運行於客戶端,或者開始嘗試事件I/O、反射器模式和npm。你會發現Node的世界是如此有趣,甚至很多Node高級技術具有某種史詩般的美感,而這些東西對於初學者來說依然是難於企及的。因此,或許你應該將你掌握的知識分享給你的同伴,尤其是對於那些不了解Node的同學,當他們開始對Node感興趣時,給他們分享傳授Node高級技術。
Node:幾個小例子
首先,你應當意識到Node是用於運行獨立的JavaScript程序的,而不是運行於浏覽器中的某個HTML片段裡。它是存放在文件系統中的真實存在的文件,由Node程序執行,以一種守護進程的模式運行,同時打開對某些端口的監聽。
跳過 hello world
最經典的例子當然是“Hello World“,在Node官網(http://nodejs.org/docs/latest )上有源碼。幾乎每個人都是從Hello World開始接觸Node的。現在讓我們跳過這個最簡單的例子,來看一些更有趣的例子:實現一個可以從服務器發送文件到客戶端的程序(而不僅僅是發送一段文本到客戶端)。
var sys = require("sys"), http = require("http"), url = require("url"), path = require("path"), fs = require("fs"); http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; var filename = path.join(process.cwd(), uri); path.exists(filename, function(exists) { if(!exists) { response.writeHead(404, {"Content-Type": "text/plain"}); response.end("404 Not Found\n"); return; } fs.readFile(filename, "binary", function(err, file) { if(err) { response.writeHead(500, {"Content-Type": "text/plain"}); response.end(err + "\n"); return; } response.writeHead(200); response.end(file, "binary"); }); }); }).listen(8080); console.log("Server running at http://localhost:8080/");
感謝Mike Amundsen,他給出了這段代碼的相似的實現。這個例子是由Devon Govett在Nettuts+上提交的一段代碼,盡管已經根據新版本的Node作了更新,但Devon的整個帖子是一個非常好的入門學習教材,對於初學者來說更是如此。
如果你是一個新手,你可以將上述代碼保存到一個文本文件中,命名為NodeFileServer.js。在運行之前你需要一個Node運行環境,最新的Node版本可以從官網下載這個文件或者從github上將源碼取下來。你需要編譯源碼,如果你沒有用過Unix、對make和configure不甚熟悉,則需要查閱在線編譯手冊來尋求幫助。
剛剛你將NodeFileServer.js存成了某個文件,別擔心,我們等下會回過頭來運行它的。現在,讓我們移步到現實當中來,在Unix中執行典型的配置和編譯命令:
./configure make make install
這讓我們確信一個事實:Node不是JavaScript,Node是一個可以運行JavaScript的程序,但Node絕對不是JavaScript。實際上,Node是基於C寫的程序。可以通過ls來查看Node/src目錄中的文件,可以看到Node的源碼:
大多數人會以為,JavaScript是一門糟糕的語言,更不用說用它來實現服務器端的功能了,其實你只對了一半。不錯,對於操作系統級別的Socket和網絡編程來說,JavaScript可能並不能勝任。但Node並不是JavaScript實現的,它是基於C實現的。C語言是可以完美的勝任任意量級的網絡編程的。而JavaScript則完全有能力將指令傳遞給C程序,然後由C程序來操控操作系統“地下城”。實際上,和C語言相比,JavaScript更容易被開發者們接觸到,這是值得引起注意的地方,如果你想用Node進行一些嚴肅的編程的話,這個原因會被一再提及。
Node的基本用法進一步反映出了Node是如何和JavaScript一起工作的,Node不是JavaScript。你可以通過命令行來運行它:
— (bdm0509@Bretts-MacBook-Pro Sun, 29 May 11) — — — — — — — — — — (/Users/bdm0509/tmp/Node/src) — — (09:09 $)-> export PATH=$HOME/local/Node/bin:$PATH — (bdm0509@Bretts-MacBook-Pro Sun, 29 May 11) — — — — — — — — — — (/Users/bdm0509/tmp/Node/src) — — (09:09 $)-> cd ~/examples — (bdm0509@Bretts-MacBook-Pro Sun, 29 May 11) — — — — — — — — — — — — (/Users/bdm0509/examples) — — (09:09 $)-> Node NodeFileServer.js Server running at http://127.0.0.1:1337/
現在你肯定對Node有個大概的了解了吧。對於這段命令行,的確還有很多知識點需要進一步解釋說明,比如在端口1337到底發生了什麼?但這裡你只需知道,Node只是一個可以讓你運行JavaScript的程序。讀者不必糾結於Node如何和JavaScript協同工作,這裡也不會對此做過多介紹,只要知道Node可以運行JavaScript,這就足夠了。而且你只需學習JavaScript這一門編程語言即可,不用擔心自己不懂C語言。記住這是最最重要的一點,不必了解C也可寫出Node可運行的程序。
剛才我們在Node上運行了NodeFileServer.js。這時你可以訪問你本機的1337端口,可以看到正常的輸出。
沒錯,輸出結果不足為奇。但應當意識到我們只用短短20行代碼就實現了一個文件服務器。輸出結果是你剛剛保存的腳本源文件的文本,並沒有以二進制的形式輸出。這個文件服務器可以輸出它上面的任何文件。如果在同樣目錄下放入一張圖片,在URL後綴中寫上圖片文件名,就像這樣:http://localhost:8080/my_image.png。
Node也可以展示出二進制的圖片文件。當你回頭再看這段短小的程序時,一定覺得這太不可思議了。用JavaScript輕易就能寫出一個你想要的服務程序難道不讓人感到惬意嗎?不僅如此,假設你想寫一個可以處理多個請求的服務(這是一個提示,同時打開四個五個甚至十個浏覽器訪問服務器),這也是很容易做到的。Node讓人著迷的地方在於,你完全可以用很簡單而且很不起眼的JavaScript程序來完成你想要的這些結果。
圍繞Node的話題總是會比純粹運行在服務器端的代碼更值得花點時間來討論。不管怎樣,我們還是從一段代碼開始我們的話題,概覽一下NodeFileServer.js文件,觀察代碼:
var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(1337, "127.0.0.1"); console.log('Server running at http://127.0.0.1:1337/');
首先調用了函數require(),require()是程序員最常用的函數之一。實際上,在CommonJS規范中也有提到這個函數,在討論到關於JavaScript模塊概念的時候有提及,此外,Davd Flanagan在2009年的一個很酷的實現中也有提到。換句話說,require()對於你來說可能是個新鮮事物,但它不是Node隨意添加的一個函數,他是使用JavaScript進行模塊化編程的核心概念,Node將這一特性發揮的淋漓盡致。
接下來,http變量用以創建一個服務器。這個服務使用一個回調函數來處理當產生一個連接時的動作。這裡的回調函數並未對請求作過多修飾,僅僅以text/plain格式輸出一個字符串“Hello World”作為請求響應。這個邏輯非常簡單。
實際上,這裡展示了使用Node的標准模式:
定義交互類型,並獲得一個用以處理這個交互的變量(通過require())。
創建一個新的服務(通過createServer())。
給服務綁定一個回調,用以處理請求。包括處理請求的函數應當包括一個請求…,以及一個響應
通知服務器啟動服務,這裡需要指定IP和端口(通過listen)。
盡管通過這種方法可以使用JavaScript輕易的實現一個服務(不管運行代碼的虛機實際上跑的是C程序還是其他什麼程序),這種做法回避了一個問題:你需要使用JavaScript寫出一個服務器嗎?為了找到這個問題的答案,我們來考慮一個非常典型的場景。
JSON的處理
這是一種非常典型的web應用,前台使用HTML和CSS,JavaScript用來作數據驗證,並和後台進行數據交互。由於你處於web交互的最頂端,你使用Ajax提交數據到後台並從後台獲取數據,而不是單單依靠表單提交來實現。如果你是這樣做的話,那麼你同樣會非常喜歡使用JSON的。JSON是如今最流行的傳輸數據的格式。
因此,這個Ajax也可以比作“把在線拍賣網站裡的某些吉他的信息發給我”。這個請求通過網絡到達一個運行PHP程序的服務器。PHP服務器不得不給JavaScript返回很多信息,而且這些信息必須以某種形式的數據包發給客戶端,而且這個數據包是可以被JavaScript解析的。因此數據可以打包成數組,然後轉換為JSON,就像這樣:
$itemGuitar = array( 'id' => 'itemGuitar', 'description' => 'Pete Townshend once played this guitar while his own axe ' . was in the shop having bits of drumkit removed from it.', 'price' => 5695.99, 'urls' => array('http://www.thewho.com', 'http://en.wikipedia.com/wiki/Pete_Townshend') ); $output = json_encode($itemGuitar); print($output);
回到客戶端,JavaScript得到這個返回的數據包,由於經過轉換,數據編程了JSON格式。就像這樣:
{ "id": "itemGuitar", "description": "Pete Townshend once played this guitar...", "price": 5695.99, "urls": ["http://www.thewho.com", "http://en.wikipedia.com/wiki/Pete_Townshend"] }
這種轉換是標准的,轉換前後也是相互等價的。接下來,就可以將這個字符串轉換為JavaScript對象,可以調用eval(),就像這樣:
var itemDetails = eval('(' + jsonDataString + ')');
計算結果是一個普通的JavaScript對象,這個對象的屬性和JSON數組的數據結構保持一致。當然,由於jsonDataString通常是由服務器返回的,通常需要這樣來解析返回結果:
var itemDetails = eval('(' + request.responseText + ')');
這就是最最典型的JSON處理,但存在一個非常嚴重的問題。
(譯注:這個小標題著實讓人費解,作者這裡拐彎抹角的解釋了Node的一個好處,就是前端和後端都采用同樣的語言JavaScript,在作JSON解析時是無障礙的,而當前端使用JavaScript作JSON編碼,後台用PHP作JSON解碼時,多少會因為多種語言的JSON解析的實現不同而帶來一些兼容性問題)
首先,這類代碼的一個主要問題是,它對解釋器的依賴比較嚴重。在上個例子中,解釋器就是指內置的JSON解析器或者實現解析JSON的代碼,這實際上依賴了兩樣東西:和eval()解析響應文本的操作一樣的基於Java的JSON解析器,以及基於PHP的JSON解析器。在PHP5.2.0中已經包含了JSON解析器,但卻是以外部依賴的形式給出的,並不是內置於PHP的內核中。
但這並不是大肆宣揚解釋器的種種。畢竟解釋器本身還存在很多問題,比如將“I”解析成了“i”,數組中的元素1解釋成了2。當然,在JSON工具正式發布之前會有大量的測試,以保證在各種復雜場景中都不會出現錯誤,包括在客戶端的解析結果和在服務器端的解析結果完全一致。無論如何,這都需要大量的測試才行。
不管怎樣,JSON依然存在很多實際的問題。
基於某種語言(基於JavaScript或者PHP)的JSON解析器選擇是一個很大的問題。換句話說,問題不是在於“翻譯”(translation)而在於“翻譯器”(translator)(譯注:作者的意思是說JSON本身的規則沒有問題,反倒是各種語言的JSON實現的質量參差不齊,甚至有很多bug)。當一個語言的版本比較穩定時,基於這門語言的JSON解析器的運用和推廣會比較快。結果是,JSON解析器變的越來越強大,以至於可以解析任意復雜的數據結構,即便這麼復雜的數據結構根本不會實際用到。反之,每次迭代中(每次計算迭代的路徑和數據類型的組合),也很有可能出現JSON解釋器無法解析的數據結構(或者很深的JSON路徑)的情況。
下圖就是可選的JSON解釋器
這並不是說JSON本身很糟糕,實際上,我們認為JSON的流行正是得益於其在新領域中的應用(譯注:作者的言外之意是,在新領域中的初次JSON實現往往伴隨很多問題)。對於新的領域,我們不禁要問:“這個新東東支持JSON嗎?” 因此,JSON需要不斷進化,需要不斷的測試,不斷的兼容新的平台。而作為程序員的,可能需要重新組織你的數據結構,或者等待新的版本出現以滿足你的需求,或者干脆直接hack JSON。而這些正是我們所說的編程資源的浪費。
假設你可以自己動手豐衣足食實現一個解釋器,即便這樣,你也沒有通過“抄近道”揀到便宜,而是用JavaScript重復造輪子而已。
而Node則規避了此類問題,剛剛你讀到的文字——關於內嵌JSON的PHP5.2.0、關於將對象轉換為數組、關於采用新的結構組織數據的方式、關於JSON中新特性的實現——這一切擾人的問題在Node中都將不復存在,因為前端通過JavaScript作JSON編碼,後台使用JavaScript作JSON解碼,永遠不會出問題。
JavaScript中eval()的潛在隱患
正如我們不用將Node當作一門新的語言來對待一樣,在Node中通過eval()來執行一段代碼也和JavaScript中的eval()一樣(不被推薦)。眾所周知eval()是非常危險的。eval()用以執行一段文本表示的代碼邏輯,可以理解為在文本框中“直接敲入SQL代碼來執行查詢”,這是不安全的,這實際上是惡意SQL注入。當每次eval()執行一段字符串的時候,(美國)中西部的一只小狗都會瑟瑟發抖,東部海灘上的某位母親的腳趾會被刺傷並受到詛咒。eval()非常危險。網上有很多關於此的資料,這裡不再贅述。可以用google查詢“eval JavaScript evil”或者“eval JavaScript injection”獲取更多信息。
當然,如果沒有任何其他上下文的約束,在Node中也是允許使用eval()的,因此eval()的隱患在Node依然存在。畢竟Node的目的並不是完全解決eval()的問題。Node被稱之為基於事件的JavaScript或基於事件的I/O,這裡所說的“基於事件”是Node中非常重要的概念。但要徹底理解什麼是基於事件,以及為什麼基於事件能讓你規避eval()的危險,則需要理解JSON在應用之中是如何工作的,此外還要搞清楚適應於web應用典型架構的特有數據結構。
傳統的Web表單提交就是典型的基於事件的模式。換句話說,在Web表單裡輸入了很多數據(用戶輸入文本框,點選復選框,從列表中選中某些項等等),之後這些數據提交給服務器。這個場景中實際是一個單一的程序事件:使用POST方式將表單數據提交。這也是基於Ajax的Web應用的工作原理。
一次性發送大量數據
對於Ajax來說,是可以和基於事件編程扯上一點關系。客戶端和服務器端之間有些交互可以認為是基於事件的。典型的場景是輸入一個省市代碼,發送請求到服務器獲得城市和省的名稱。這裡通過XmlHttpRequest的Ajax並不需要將很多數據一次性扔給服務器。但這並不能改變大部分web應用都是基於頁面刷新這種模式的現狀。Ajax已經更廣泛的用於很多有意思的視覺相關的交互,快速的作表單驗證,無刷新提交數據,這樣就可以避免重新載入頁面。因此,盡管並未通過提交表單來發起一個真正的POST請求,通過Ajax可以模擬POST表單提交。
坦率的講,這種傳統的Ajax交互方式也阻礙了Ajax程序員的創新。每次發送一個請求時(不管請求的數據多麼小),都會在網絡裡走一個來回。服務器必須針對這個請求作出響應,通常是開辟一個新的進程。因此,如果你真正置身於一個事件模型的環境中作開發,你可能需要通過發起10到15個單獨的小請求來保持你的頁面和服務器之間的聯系,服務器也會為之創建10到15個線程(可能更少,這取決於服務器處理新請求時分配線程池的策略),當這個數量乘以1000或者10000或者100000時(譯注:每個頁面需要10個請求,那麼越多用戶訪問這個頁面,所發起的請求個數就會越來越多),就會出現內存溢出、邏輯交錯帶來的沖突、網絡癱瘓、系統崩潰這些問題。
結果是,在大多數場景中,Web應用需要保持對事件的最小依賴。有一個折衷方案,就是服務器端程序的響應返回的不是一個微小的數據片段,而是帶有更多冗余數據結構的數據包,通常是JSON數據,這時就又遇到了eval()的問題。問題當然出在eval()身上,但這也和Web本身和服務器線程控制、包括頁面和服務器之間的HTTP請求和響應策略(至少在這個場景下)有密不可分的關系。
或許有些人對上文提到的問題不以為然,因為你知道有很多方法來規避直接eval()帶來的問題,你會使用諸如JSON.parse()來代替eval()。同樣有很多令人信服的論據鼓勵我們小心的使用eval()。這些東東都是值得進一步討論的。但不管怎樣,看一看eval()帶來了太多類似棧溢出(Stack Overflow)這類的問題吧,你會發現大部分程序員並未正確或者安全的使用eval()。這著實是一個問題。因為太多菜鳥程序員似乎根本沒有意識到eval()的問題有多嚴重。
不斷的發送少量的數據
Node帶來了架構應用的新思路,我們可以基於Node采用事件模型來架構Web應用,或者說“小型的”事件模型。換句話說,你應當基於大量的事件發送大量的請求,每個請求的數據包都很小,或者根據需要從後台抓取少量數據,而不是發送很少的請求,每次請求都帶有大量的數據。在很多場景中,大多數情況下你需要喚醒GUI程序(Java Swing程序員的GUI知識儲備可以派上用場了)。因此,當用戶輸入姓氏和名字後,移步到下一個輸入框,這時就已經發起了一個請求來驗證輸入的用戶名是否已經存在。省市代碼、地址和電話號碼的驗證也是同理。頁面上每發生一個時間,都會產生一個請求和響應。
這有什麼不同嗎?為什麼Node可以做到,並規避了已有的線程問題?其實Node並沒有這麼神秘,Node官網充分解釋了其哲學:
Node的目標是提供一種構建可伸縮的網絡應用的方案,在hello world例子中,服務器可以同時處理很多客戶端連接。Node和操作系統有一種約定,如果創建了新的鏈接,操作系統就將通知Node,然後進入休眠。如果有人創建了新的鏈接,那麼它(Node)執行一個回調,每一個鏈接只占用了非常小的(內存)堆棧開銷。
Node是無阻塞的,不會出現同源競爭線程的情況(Node非常樂於處理即時的請求,發生了什麼事情,那就讓他發生吧),新請求到達服務器時,不需要為這個請求單獨作什麼事情。Node僅僅是悠閒的坐在那裡等待(請求的發生),有請求就處理請求。用非常簡單的代碼就可以實現,而不用花費程序員寶貴的精力去實現一整套服務器端邏輯。
沒錯,混亂不可避免
值得一提的是,非阻塞系統帶來的問題也會出現在這種編程模式中:一個進程(非線程)等待一個數據存儲操作,這時產生了另外一個抓取與之無關的數據的操作,這個意外的操作會對現有的等待造成影響(譯注:作者的意思是說多個操作同時發生或者沒有按照預定順序發生時,會產生混亂,也就是說,操作本身並不是原子性的)。但要注意,大多數基於事件的web編程模式都是“只讀的”!你大概也沒有遇到過通過“微請求”來修改數據的情況,或者說非常罕見。相反,通過這種請求來驗證數據合法性、查詢數據的情形則非常常見。這種情況下,最好直接根據請求作響應。數據庫本身會作加鎖操作,一般來講,一個優秀的數據庫完全可以高效的做到數據操作的加鎖解鎖,而不用服務器端的程序代碼去多做什麼。而Node又比操作系統處理線程的保持和釋放更加高效,使得服務器不必單獨為“web響應”開辟一個進程。
此外,Node也計劃實現“進程分支”(process forking),HTML5 Web Workers API為更復雜的進程控制提供了引擎(規范)支持。同樣,如果你采用基於事件的模型來架構web應用,你的程序可能至少有100多個場景需要線程的支持。最終你會發現,你的編程思路和思考問題的方式發生了改變,你的注意力將放在服務器端處理請求的邏輯上,而不必在乎Node如何工作。
這裡我們討論另外一種web開發模式,不管是不是采用了Node、或者是不是采用了基於事件的編程模式,這都無關緊要,因為這種模式實在太重要了。簡言之:對症下藥!概括講就是,針對不同的問題采取不同的解決方案,而不管這種解決方案是否解決其他問題。
思維定勢
不止在web設計領域,在所有編程之中都存在某種思維定勢。可以這麼描述這種思維定勢:你學到的、掌握的越多,你能解決的問題就越多,你所掌握的技能的應用場景也就越多。這看起來理所當然,除非你在技術上鑽研的更深。沒錯,學習新的語言和新的工具並廣泛使用它總不是壞事。但往往會進入一個誤區,就是,因為你了解它,所以你使用它,而不是因為你所掌握的技能和工具是“最適合”你的業務的。
我們來看一下Ajax,關於Ajax已經有太多太多的討論了。我們知道,Ajax為無刷新的快速查詢請求提供了可靠的解決方案。而如今因為Ajax的濫用以至於過分替代了傳統的表單提交。我們遇到一個新技術、學習它、掌握它、應用它,然後“濫用它”。畢竟很多業務場景僅僅需要傳統的表單提交,而不需要Ajax。說起來簡單,實際上還有成千上萬的濫用Ajax的案例場景,僅僅因為某個應用的開發工程師對Ajax的盲目尊崇。
同樣的,Node也面臨這樣一個問題。當你初識Node發現它的種種好處,就想到處使用它。就會一股腦的將PHP或Perl程序換成Node。結果呢?糟透了。其實你已經害上了強迫症,總是想將Node用於有違其設計初衷的場景中:使用JavaScript提交大量數據給Node,或者通過Node返回給JavaScript大量的JSON數據,交給前端去作eval(),或者干脆使用Node作一個文件服務器用以返回HTML頁面或做HTTP重定向。
但這些場景均不是Node所擅長的。Node更擅長處理體積小的請求以及基於事件的I/O,使用Node解決客戶端和服務器之間的快速溝通,使用表單提交將大量的數據發送給服務器,使用PHP和Perl來處理重型數據庫操作以及動態HTML頁面的生成。使用Node運行於服務器端來處理體積不大的請求。不管是采用Rails還是Spring以及各式各樣的服務端容器,只要按需索取即可。一定要明白你需要解決的問題是什麼,基於此采取最佳解決方案,而不是基於你當下所掌握的技能來解決遇到的問題。
Node的簡單的初衷
還有最後一點需要注意,當你越來越深入你的編程時,你會發現你不必每個工具、API和所使用的框架都達到精通。將刀用在刀刃上,不要將錘子當成鑽頭來使用。了解每個工具所適用的場景和能解決的問題,然後找到這個工具的最適合的應用場景。如果你想變成超人式的通才(程序員往往什麼都想知道),你離“專家”也就越來越遠,所謂專家,就是指在一兩個方面達到非常精通。當然,每個老板都希望能找到超人式的通才,但這種人往往可遇不可求。
學習Node可能會有些吃力,但是非常值得的。為什麼?因為你正在尋求基於JavaScript的web應用的解決方案。這意味著你已有的JavaScript編程技能不會丟掉,當你需要使用PHP或者Perl時,你必須重新學習一門新的語言,而Node不必如此大動干戈。學習新語言帶來的問題比學習他們帶來的好處要大的多。
學習Node所面臨的挑戰是,你需要更加活躍思維,將程序拆成低耦合的小片段,然後像組裝數組一樣的組裝他們。但Node和基於事件的I/O並不能解決所有問題,但確定的是,很多關鍵問題,只能依靠Node來解決。
Node:Up and Running
The secrets of Node’s success
Why a JavaScript hater thinks everyone needs to learn JavaScript in the next year
JavaScript spread to the edges and became permanent in the process
What is Node.js and what does it do?