這個問題可不好回答(至少對我來說),不過這是Node.js原生的工作方式。它是事件驅動的,這也是它為什么這么快的原因。
你也許會想花點時間讀一下Felix Geisend?rfer的大作 [Understanding node.js](http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb),它介紹了一些背景知識。
這一切都歸結于“Node.js是事件驅動的”這一事實。好吧,其實我也不是特別確切的了解這句話的意思。不過我會試著解釋,為什么它對我們用Node.js寫網絡應用(Web based application)是有意義的。
當我們使用?_http.createServer_?方法的時候,我們當然不只是想要一個偵聽某個端口的服務器,我們還想要它在服務器收到一個HTTP請求的時候做點什么。
問題是,這是異步的:請求任何時候都可能到達,但是我們的服務器卻跑在一個單進程中。
寫PHP應用的時候,我們一點也不為此擔心:任何時候當有請求進入的時候,網頁服務器(通常是Apache)就為這一請求新建一個進程,并且開始從頭到尾執行相應的PHP腳本。
那么在我們的Node.js程序中,當一個新的請求到達8888端口的時候,我們怎么控制流程呢?
嗯,這就是Node.js/JavaScript的事件驅動設計能夠真正幫上忙的地方了——雖然我們還得學一些新概念才能掌握它。讓我們來看看這些概念是怎么應用在我們的服務器代碼里的。
我們創建了服務器,并且向創建它的方法傳遞了一個函數。無論何時我們的服務器收到一個請求,這個函數就會被調用。
我們不知道這件事情什么時候會發生,但是我們現在有了一個處理請求的地方:它就是我們傳遞過去的那個函數。至于它是被預先定義的函數還是匿名函數,就無關緊要了。
這個就是傳說中的?_回調_?。我們給某個方法傳遞了一個函數,這個方法在有相應事件發生時調用這個函數來進行?_回調_?。
至少對我來說,需要一些功夫才能弄懂它。你如果還是不太確定的話就再去讀讀Felix的博客文章。
讓我們再來琢磨琢磨這個新概念。我們怎么證明,在創建完服務器之后,即使沒有HTTP請求進來、我們的回調函數也沒有被調用的情況下,我們的代碼還繼續有效呢?我們試試這個:
~~~
var http = require("http");
function onRequest(request, response) {
? console.log("Request received.");
? response.writeHead(200, {"Content-Type": "text/plain"});
? response.write("Hello World");
? response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
~~~
注意:在?_onRequest_?(我們的回調函數)觸發的地方,我用?_console.log_?輸出了一段文本。在HTTP服務器開始工作_之后_,也輸出一段文本。
當我們與往常一樣,運行它_node server.js_時,它會馬上在命令行上輸出“Server has started.”。當我們向服務器發出請求(在瀏覽器訪問[http://localhost:8888/](http://localhost:8888/)),“Request received.”這條消息就會在命令行中出現。
這就是事件驅動的異步服務器端JavaScript和它的回調啦!
(請注意,當我們在服務器訪問網頁時,我們的服務器可能會輸出兩次“Request received.”。那是因為大部分服務器都會在你訪問 `http://localhost:8888` /時嘗試讀取 `http://localhost:8888/favicon.ico` )