基於事件驅動的回撥

當我們使用 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/),“Request received.”這條訊息就會在命令列中出現。

這就是事件驅動的非同步伺服器端JavaScript和它的回撥啦!

(請注意,當我們在伺服器訪問網頁時,我們的伺服器可能會輸出兩次“Request received.”。那是因為大部分伺服器都會在你訪問 http://localhost:8888 /時嘗試讀取 http://localhost:8888/favicon.ico )


.