what it is?
- Node.js的本質是一個Javascript的解析器
- Node.js是Javascript 的執行環境
- Node.js是一個伺服器程式
- Node.js本身使用的是V8引擎
- Node不是web伺服器
Why use it?
- 為了提供高效能的web服務
- IO效能強大
- 事件處理機制完善
- 天然能夠處理DOM
- 社群非常活躍,生態圈日趨完善
The advantage
- 處理大流量資料
- 適合實時互動的應用
- 完美支援物件資料庫
- 非同步處理大量併發連結
安裝cnpm
- npm install cnpm 安裝cnpm
第一個node程式
- 建立 hello.js 並編輯 console.log("helloworld")
- node hello.js //執行
#node最簡單的web服務
-
建立 server.js
-
引入 原生 api
var http = require('htttp');
複製程式碼
- 建立一個服務
http.createServer(function (request,response) {
//定義HTTP頭
response.writeHead(200, {'Content-Type':'text/plan'});
//傳送相應的資料
response.end('Hello world!\n');
}).listen(8000);
//服務執行之後輸出一行資訊
console.log('server is running...');
複製程式碼
- 執行
node server.js
複製程式碼
- 開啟瀏覽器 127.0.0.1:8000
Nodejs 環境及npm命令的深入
REPL
全稱互動式直譯器 敲 node 命令進入 可以在環境之後 直接進行程式碼 的編寫 運算 優點類似 瀏覽器的 console控制檯 一般來說我們可以在此環境下 進行一些 簡單的 程式碼運算 驗證
- ctrl + c -退出當前終端
- ctrl + c -按下兩次 退出 Node REPL
- ctrl + d -退出Node REPL (linux環境下)
- 向上/向下 鍵 -檢視輸入的歷史命令
- tab鍵 -列出當前命令
- .help -列出使用命令
- .break -退出多行表示式
- .clear -退出多行表示式
- .save filename -儲存當前的Node REPL 會話到指定檔案
- .load filename -載入當前 Node REPL 會話的檔案內容。
npm包管理器
- npm install npm -g //升級npm
- npm install express -g//安裝包express
- npm uninstall packagename // 解除安裝包
- npm search packagename // 查詢包
- npm help
- npm help install // 具體檢視 某個命令
- cnpm 與 npm 的使用方法本質是相同的 只是伺服器不同 一個國內 一個國外
什麼是回撥
- 函式呼叫方式分為三類 :同步呼叫、回撥和非同步呼叫。
- 回撥時一種雙向呼叫模式
- 可以通過回撥函式來實現回撥
阻塞與非阻塞
- 阻塞和非阻塞關注的是程式在等待呼叫的結果(訊息,返回值)時的狀態。
- 阻塞就是做不完不準回來
- 非阻塞就是你先做,我現在看看有其他事沒有,做完了告訴我一聲
//阻塞時程式碼
var fs = require('fs');
var data = fs.readFileSync('data.txt'); // 阻塞時用 同步讀取 readFileSync 非阻塞時用 readFile
console,log(data.toString());
複製程式碼
//非阻塞程式碼
var fs = require('fs');
fs.readFile('filename.txt',function(err,data){
// todo something
if(err){
return console.error(err)
}
console.log(data.toString());
})
cosnole.log("程式執行完畢")
複製程式碼
Node.js事件驅動機制
事件驅動模型
事件與事件繫結
- nodejs 是一個單程式 單執行緒的程式,它並不能同時併發完成更多的事情,只能通過事件或者回撥來實現併發效果
- nodejs 的 api 全都是非同步執行的,而且都是作為獨立的執行緒處理的
- nodejs 中的 幾乎所有的事件 都是依據觀察者模式 來實現的 觀察者模式 是設計模式中的一種
- EventEmitters 物件 產生 Events 例項
事件處理程式碼
//1. 引入 events物件,建立 eventEmitter物件
var events = require('events');
var eventEmitter = new events.EventEmmitter();
//2. 繫結事件處理程式
var connctHandler = function connected(){
console.log('connected被呼叫了');
};
eventEmitter.on('connection', connctHandler()); //完成事件繫結
//3.觸發事件
eventEmitter.emit('connection');
console.log("程式執行完畢");
複製程式碼
Nodejs 模組化
模組化的概念和意義
- 為了讓Node.js的檔案可以相互呼叫,Node.js提供了一個簡單的模組系統
- 模組是Node.js應用程式的基本組成部分
- 檔案和模組是一一對應的。一個Node.js檔案就是一個模組
- 這個檔案可能是Javascript程式碼、JSON或者編譯過的C/C++擴充套件
- Node.js中存在4類模組(原生模組和3種檔案模組)
Node.js中的模組
Node.js的模組載入流程
檔案的快取區 有檔案模組快取區 和 原生模組快取區
- require 方法接受一下幾種引數的傳遞: 1 http、fs、path等,原生模組 2 ./mod或../mod,相對路徑的檔案模組 3 /pathtomodule/mo,絕對路徑的檔案模組
- mod,非原生模組的檔案模組
模組化程式碼案例
//main.js 主要呼叫模組的檔案
var Hello = require('./hello');
hello = new Hello();
hello.setName('Richard');
hello.sayHello();
//hello.js 模組檔案
function Hello(){
var name ;
this.setName = function(argName){
name = argName
}
this.sayHello = function(){
console.log('hellko' + name);
}
}
module.exports = Hello;
複製程式碼
函式
- 在javascript 中,一個函式可以作為另一個函式的引數。
- 我們可以先定義一個函式,然後傳遞,也可以在傳遞引數的地方直接定義函式。
- Nodejs 中的函式使用與Javascript 類似
程式碼示例:
function say(word){
console.log(word);
}
function execute(someFunction,value){
someFunction(value);
}
execute(say,'hello')
複製程式碼
匿名函式
function execute(someFunction,value){
someFunction(value)
}
execute(function(word){
console.log(word)
},'hello');
複製程式碼
示例Ⅱ 同樣的功能,不同的實現方式
//匿名函式
var http = require('http');
http.createServer(function(request,response){
response.writeHead(200,{"Content-Type":'text/plain'});
response.write("Hello world");
response.end();
}).listen(8000)
//先定義後傳遞
var http = require("http");
function onResquest(request,reponse){
response.writeHead(200,{"Content-Type":'text/plain'});
response.write("Hello World");
response.end();
}
http.createServer(onResquest).listen(8888);
複製程式碼
路由
我們所需要的所有資料都會包含在request物件中,該物件作為onRequest()回撥函式的第一個引數傳遞。但是為了解析這些資料,我們需要額外的Node.JS模組,他們分別是url 和querystring模組
例如我們 訪問 http://localhost:8888/start?foo=bar&hello=world
url.parse(string).query
|
url.parse(string).pathname |
| |
| |
------ -------------------
http://localhost:8888/start?foo=bar&hello=world
--- -----
| |
| |
querystring.parse(queryString)["foo"] |
|
querystring.parse(queryString)["hello"]
複製程式碼
//server.js
var http = require("http");
var url = require("url");
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
//console.log("Request for " + pathname + " received.");
route(pathname,response);
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
//router.js
function route(pathname,response) {
if(pathname == '/'){
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}else if(pathname == "/index/home"){
response.end('index');
}else{
response.end('index');
}
}
exports.route = route;
//app.js
var server = require("./server");
var router = require("./router");
server.start(router.route);
複製程式碼
獲取GET請求內容
var http = require('http');
var url = require('url');
var util = require('util'); //幫助類
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
res.end(util.inspect(url.parse(req.url, true)));
}).listen(3000);
複製程式碼
獲取POST請求內容
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res){
// 定義了一個post變數,用於暫存請求體的資訊
var post = '';
// 通過req的data事件監聽函式,每當接受到請求體的資料,就累加到post變數中
req.on('data', function(chunk){
post += chunk;
});
// 在end事件觸發後,通過querystring.parse將post解析為真正的POST請求格式,然後向客戶端返回。
req.on('end', function(){
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
複製程式碼
全域性物件與全域性變數
global 就是nodejs的全域性物件 類比javascript的window
-
__filename __filename 表示當前正在執行的指令碼的檔名。它將輸出檔案所在位置的絕對路徑,且和命令列引數所指定的檔名不一定相同。 如果在模組中,返回的值是模組檔案的路徑。
-
__dirname __dirname 表示當前執行指令碼所在的目錄。
-
setTimeout(cb, ms) setTimeout(cb, ms) 全域性函式在指定的毫秒(ms)數後執行指定函式(cb)。:setTimeout() 只執行一次指定函式。返回一個代表定時器的控制程式碼值。
-
clearTimeout(t) clearTimeout( t ) 全域性函式用於停止一個之前通過 setTimeout() 建立的定時器。 引數 t 是通過 setTimeout() 函式建立的定時器。
-
setInterval(cb, ms) setInterval(cb, ms) 全域性函式在指定的毫秒(ms)數後執行指定函式(cb)。返回一個代表定時器的控制程式碼值。可以使用 clearInterval(t) 函式來清除定時器。setInterval() 方法會不停地呼叫函式,直到 clearInterval() 被呼叫或視窗被關閉。
-
process process 是一個全域性變數,即 global 物件的屬性。它用於描述當前Node.js 程式狀態的物件,提供了一個與作業系統的簡單介面。通常在你寫本地命令列程式的時候,少不了要 和它打交道。下面將會介紹 process 物件的一些最常用的成員方法。
工具util
underscore.js
檔案系統
讀取檔案
var fs = require("fs");
// 非同步讀取
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("非同步讀取: " + data.toString());
});
// 同步讀取
var data = fs.readFileSync('input.txt');
console.log("同步讀取: " + data.toString());
console.log("程式執行完畢。");
複製程式碼
開啟檔案
fs.open(path, flags[, mode], callback) 引數說明:
- path - 檔案的路徑。
- flags - 檔案開啟的行為。
- mode - 設定檔案模式(許可權),檔案建立預設許可權為 0666(可讀,可寫)。
- callback - 回撥函式,帶有兩個引數如:callback(err, fd)。
獲取檔案資訊
fs.stat(path, callback) 引數說明
- path - 檔案路徑。
- callback - 回撥函式,帶有兩個引數如:(err, stats), stats 是 fs.Stats 物件。
寫入檔案
fs.writeFile(file, data[, options], callback)
- file - 檔名或檔案描述符。
- data - 要寫入檔案的資料,可以是 String(字串) 或 Buffer(緩衝) 物件。
- options - 該引數是一個物件,包含 {encoding, mode, flag}。預設編碼為 utf8, 模式為 0666 , flag 為 'w'
- callback - 回撥函式,回撥函式只包含錯誤資訊引數(err),在寫入失敗時返回。
var fs = require("fs");
console.log("準備寫入檔案");
fs.writeFile('input.txt', '我是通 過fs.writeFile 寫入檔案的內容', function(err) {
if (err) {
return console.error(err);
}
console.log("資料寫入成功!");
console.log("--------我是分割線-------------")
console.log("讀取寫入的資料!");
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("非同步讀取檔案資料: " + data.toString());
});
});
複製程式碼
等等 方法 參考 菜鳥教程