Node.js:創建應用+回調函數(阻塞/非阻塞)
一、創建應用
如果我們使用PHP來編寫後端的代碼時,需要Apache 或者 Nginx 的HTTP 服務器,並配上 mod_php5 模塊和php-cgi。從這個角度看,整個"接收 HTTP 請求並提供 Web 頁面"的需求根本不需要 PHP 來處理。
不過對 Node.js 來說,概念完全不一樣了。使用 Node.js 時,我們不僅僅在實現一個應用,同時還實現了整個 HTTP 服務器。事實上,我們的 Web 應用以及對應的 Web 服務器基本上是一樣的。
在我們創建 Node.js 第一個 "Hello, World!" 應用前,讓我們先了解下 Node.js 應用是由哪幾部分組成的:
-
引入 required 模塊:我們可以使用 require 指令來載入 Node.js 模塊。
-
創建服務器:服務器可以監聽客戶端的請求,類似於 Apache 、Nginx 等 HTTP 服務器。
-
接收請求與響應請求 服務器很容易創建,客戶端可以使用瀏覽器或終端發送 HTTP 請求,服務器接收請求後返回響應數據
1、引入 required 模塊
我們使用 require 指令來載入 http 模塊,並將實例化的 HTTP 賦值給變量 http,實例如下:
2、創建服務器
接下來我們使用 http.createServer() 方法創建服務器,並使用 listen 方法綁定 8888 端口。 函數通過 request, response 參數來接收和響應數據。
實例如下,在你項目的根目錄下創建一個叫 server.js 的文件,並寫入以下代碼:
var http = require("http")
http.createServer(function(request,response){
// 發送 HTTP 頭部
// HTTP 狀態值: 200 : OK
// 內容類型: text/plain
response.writeHead(200, {‘Content-Type‘: ‘text/plain‘});
// 發送響應數據 "Hello World"
response.end(‘Hello World\n‘);
}).listen( 8888)
// 終端打印如下信息
console.log(‘Server running at http://127.0.0.1:8888/‘);
以上代碼我們完成了一個可以工作的 HTTP 服務器。使用 node 命令執行以上的代碼,打開瀏覽器訪問 http://127.0.0.1:8888/,你會看到一個寫著 "Hello World"的網頁。
分析Node.js 的 HTTP 服務器:第一行請求(require)Node.js 自帶的 http 模塊,並且把它賦值給 http 變量。接下來我們調用 http 模塊提供的函數: createServer 。這個函數會返回 一個對象,這個對象有一個叫做 listen 的方法,這個方法有一個數值參數, 指定這個 HTTP 服務器監聽的端口號。
二、回調函數
Node.js 異步編程的直接體現就是回調。異步編程依托於回調來實現,但不能說使用了回調後程序就異步化了。回調函數在完成任務後就會被調用,Node 使用了大量的回調函數,Node 所有 API 都支持回調函數。例如,我們可以一邊讀取文件,一邊執行其他命令,在文件讀取完成後,我們將文件內容作為回調函數的參數返回。這樣在執行代碼時就沒有阻塞或等待文件 I/O 操作。這就大大提高了 Node.js 的性能,可以處理大量的並發請求。
1、阻塞代碼實例
var fs = require("fs");
var data = fs.readFileSync(‘input.txt‘);
console.log(data.toString());
console.log("程序執行結束!");
//結果:先打印input裏面內容,再打印程序結束
2、非阻塞代碼實例
var fs = require("fs");
fs.readFile(‘input.txt‘, function (err, data) {
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序執行結束!");
//結果:先打印程序結束,再打印input裏面內容
以上兩個實例我們了解了阻塞與非阻塞調用的不同。第一個實例在文件讀取完後才執行完程序。 第二個實例我們不需要等待文件讀取完,這樣就可以在讀取文件時同時執行接下來的代碼,大大提高了程序的性能。
因此,阻塞是按順序執行的,而非阻塞是不需要按順序的,所以如果需要處理回調函數的參數,我們就需要寫在回調函數內。
3、阻塞和非阻塞,同步異步的理解
阻塞和非阻塞,同步和異步是node.js裏經常遇到的詞匯,我舉個簡單的例子來說明:
我要看足球比賽,但是媽媽叫我燒水,電視機在客廳,燒水要在廚房。家裏有2個水壺,一個是普通的水壺,另一個是水開了會叫的那種水壺。我可以:
(1)用普通的水壺燒,人在邊上看著,水開了再去看球。(同步,阻塞)這個是常規做法,但是我看球不爽了。
(2)用普通水壺燒,人去看球,隔幾分鐘去廚房看看。(同步,非阻塞)這個又大問題,萬一在我離開的幾分鐘水開了,我就麻煩了。
(3)用會叫的水壺,人在邊上看著。(異步,阻塞)這個沒有問題,但是我太傻了。
(4)用會叫的水壺,人去看球,聽見水壺叫了再去看。(異步,非阻塞)這個應該是最好的。
等著看球的我:阻塞,看著電視的我:非阻塞
普通水壺:同步,會叫的水壺:異步
所以,異步往往配合非阻塞,才能發揮出威力。
Node.js:創建應用+回調函數(阻塞/非阻塞)