作者:燁竹
本文參考:
https://www.w3cschool.cn/nodejs/
https://nodejs.org/dist/latest-v8.x/docs/api/synopsis.html
http://www.runoob.com/nodejs/nodejs-install-setup.html
簡(jiǎn)介:Node.js是一個(gè)Javascript運(yùn)行環(huán)境(runtime)准给。實(shí)際上它是對(duì)Google V8引擎進(jìn)行了封裝祖灰。V8引 擎執(zhí)行Javascript的速度非尘址觯快,性能非常好畴蒲。Node.js對(duì)一些特殊用例進(jìn)行了優(yōu)化,提供了替代的API蔫骂,使得V8在非瀏覽器環(huán)境下運(yùn)行得更好
使用Sublime 編譯nodeJS
開(kāi)啟Sublime應(yīng)用程式辽旋,接下來(lái)锅减,選功能列 Tools/Build System/New Build System…
此時(shí)怔匣,會(huì)出現(xiàn)一個(gè)這樣的檔案 untitled.sublime-build 將內(nèi)容修改成:
{
"cmd": ["C:/Program Files/nodejs/node.exe", "$file"]
}
并修改儲(chǔ)存成NodeJS.sublime-build
測(cè)試:寫(xiě)一些js代碼,保存剿骨,按Ctrl+B查看編譯結(jié)果
node.js應(yīng)用組成
1浓利、引入 required 模塊:我們可以使用 require 指令來(lái)載入 Node.js 模塊嫡秕。
2昆咽、創(chuàng)建服務(wù)器:服務(wù)器可以監(jiān)聽(tīng)客戶(hù)端的請(qǐng)求窟哺,類(lèi)似于 Apache 糕殉、Nginx 等 HTTP 服務(wù)器。
3羡洁、接收請(qǐng)求與響應(yīng)請(qǐng)求 服務(wù)器很容易創(chuàng)建,客戶(hù)端可以使用瀏覽器或終端發(fā)送 HTTP 請(qǐng)求,服務(wù)器接收請(qǐng)求后返回響應(yīng)數(shù)據(jù)秸应。
//引入required模塊
var http = require('http');
http.createServer(function (request, response) {
// 發(fā)送 HTTP 頭部
// HTTP 狀態(tài)值: 200 : OK
// 內(nèi)容類(lèi)型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 發(fā)送響應(yīng)數(shù)據(jù) "Hello World"
response.end('Hello World\n');
}).listen(8888);
// 終端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
node server.js
Server running at http://127.0.0.1:8888/
模塊
Node.js 有三大類(lèi)的模塊(module Types)
Core Modules (原生模塊)
Local Modules (自建模塊)
Third Party Modules (第三方模塊)
Core Modules (原生模塊)
載入Core Modules
var module = require(‘module_name’);
載入modules 的注意事項(xiàng)
var log = require('./utility');
nodeJS把整個(gè)utility資料夾延柠,當(dāng)成一個(gè)包盈罐,所以闪唆,它會(huì)自動(dòng)在這個(gè)資料夾里去找package定義文件盅粪,預(yù)設(shè)為package.json,之后悄蕾,再根據(jù)定義文件里的關(guān)鍵字main描述的檔名票顾,載入檔案。所以解決方案為自行定義一個(gè)package.json放在此utility資料夾里
./untility/package.json
{
"name" : "log",
"main" : "./log.js"
}
本地自動(dòng)化功能操作:(module_name)
[http](https://nodejs.org/api/http.html):它包含可以用來(lái)建立http server的一些類(lèi)別,方法,及事件帆调。
[url](https://nodejs.org/api/url.html):它包含可以解析url的一些方法奠骄。
[querystring](https://nodejs.org/api/querystring.html):它包含可以處理由client端傳來(lái)querystring的一些方法。
[path](https://nodejs.org/api/path.html):它包含可以處理一些檔案或資料夾路徑的方法枣抱。
[fs](https://nodejs.org/api/fs.html):它包含檔案的存戎械/操作的一些類(lèi)別铝侵,方法及事件颖侄。
[util](https://nodejs.org/api/util.html):它包含一些可供程序者使用的效能函式。
自建模塊
log.js(新建)
var log = {
info: function (info) {
console.log('Info: ' + info);
},
warning:function (warning) {
console.log('Warning: ' + warning);
},
error:function (error) {
console.log('Error: ' + error);
}
};
module.exports = log //這一部很重要,只要,模組(程式)要給別的模組(程式)使用械媒,必須加這個(gè)!!
LogApp.js(使用)
var myLogModule = require('./Log.js');
myLogModule.info('Node.js started');
結(jié)果:
詳解:Exports 物件(exports是一個(gè)物件耍攘,所以嚷硫,我們可以直接分派 屬性负懦,函式(方法)及物件給它)
屬性
exports.SimpleMessage = 'Hello world';
//or
module.exports.SimpleMessage = 'Hello world';
使用函式
module.exports.log = function (msg) {
console.log(msg);
};
使用物件
module.exports = {
firstName: 'James',
lastName: 'Bond'
}
Exports 函式(直接分派一個(gè)匿名函式給exports)
module.exports = function (msg) {
console.log(msg);
};
Exports 類(lèi)別化函式
module.exports = function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function () {
return this.firstName + ' ' + this.lastName;
}
}
NMP管理
簡(jiǎn)單介紹
npm -v
npm install npm -g //更新nmp
npm help
區(qū)域安裝(你可以在你的應(yīng)用文件夾里,安裝你想要的套件炼七,)語(yǔ)法
npm install <package name> //注意這里要cd到要安裝的文件夾
舉例說(shuō)明如下
C:\cs> npm install express
生成兩個(gè)軟件
當(dāng)然,里頭也包含了你所安裝的express.js模組也在express資料夾內(nèi)
全域安裝語(yǔ)法
npm install -g express
更新套件
npm update <package name>
解除安裝套件
npm uninstall <package name>
更多npm資訊
https://docs.npmjs.com/
Web Server
處理Http Request
http.createServer() 方法止剖,包含Node.js 提供的request 及respones 二個(gè)參數(shù)待德。
request 物件可以用來(lái)得到一些從http server 發(fā)過(guò)來(lái)的請(qǐng)求耙厚,例如url、http header 及data价卤。
response 物件則送出回應(yīng)給Http 送來(lái)的請(qǐng)求
建立
// var http = require('http'); // 1 - 載入 Node.js 原生模組 http
// var server = http.createServer(function (request, response) { // 2 - 建立server
// // 在此處理 客戶(hù)端向 http server 發(fā)送過(guò)來(lái)的 req岁疼。
// });
// server.listen(5000); //3 - 進(jìn)入此網(wǎng)站的監(jiān)聽(tīng) port, 就是 localhost:xxxx 的 xxxx
// console.log('Node.js web server at port 5000 is running..')
//
var http=require('http');
var server=http.createServer(function(req,res){
if(req.url=='/'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is Home Page.</body></html>');
res.end();
}else if(req.url=='/student'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is student Page.</body></html>');
res.end();
}else if(req.url=='/admin'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is admin Page.</body></html>');
res.end();
}else
res.end('Invalid Request!');
});
server.listen(5000);
返回json
var http = require('http');
var server = http.createServer(function (req, res) {
if (req.url == '/') { //check the URL of the current request
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify({ message: "Hello World"}));
res.end();
}
});
server.listen(5000);
console.log('Node.js web server at port 5000 is running..')
文件操作
Node.js的fs module 兽肤,是用來(lái)操作實(shí)體檔案沮明,可以同步或非同步存取檔案系統(tǒng)操作。一般建議使用非同步存取檔案窍奋,性能高荐健、速度快、無(wú)阻塞
非同步讀取檔案語(yǔ)法
fs.readFile(fileName [,options], callback)
fileName: 檔案的完整路徑及檔名琳袄,格式字串江场。
options: options 可能是一個(gè)物件或字串,包含"編碼"及"flag"窖逗。這里預(yù)設(shè)的編碼是utf8 , flag是"r"址否。
call back: 是帶兩個(gè)參數(shù)的function,err及file data碎紊,當(dāng)我們執(zhí)行readFile完成時(shí), 要做的事, 例如: 回傳file data
例子:
var fs = require('fs');
fs.readFile('TestFile.txt', function (err, data) {
if (err) throw err;
console.log(data.toString());
});
我們執(zhí)行完讀取檔案操作佑附,它會(huì)執(zhí)行function,如果有錯(cuò)誤矮慕,會(huì)回傳錯(cuò)誤帮匾;成功,會(huì)回傳所讀取的檔案資料痴鳄。如圖:
同步讀取檔案
var fs = require('fs');
var data = fs.readFileSync('dummyfile.txt', 'utf8');
console.log(data);
寫(xiě)入文件(fs.writeFile() 寫(xiě)入檔案瘟斜,如果檔案存在,會(huì)覆寫(xiě)原本檔案資料;否則會(huì)自動(dòng)新增檔案并寫(xiě)入資料)
fs.writeFile(filename, data[, options], callback)
fileName:檔案的完整路徑及檔名螺句,格式字串虽惭。
● data:要寫(xiě)入的檔案內(nèi)容。
● options: options可能是一個(gè)物件或字串蛇尚,包含"編碼"及"flag"芽唇。這里預(yù)設(shè)的編碼是utf8 , flag是"w"。
● call back:只帶一個(gè)錯(cuò)誤參數(shù)err的function取劫,當(dāng)我們執(zhí)行writeFile完成時(shí),要做的事匆笤。例如:寫(xiě)入成功的訊息顯示;失敗時(shí)谱邪,丟出err炮捧。
開(kāi)啟檔案
fs.open(path, flags[, mode], callback)
path: 檔案的完整路徑及檔名,格式字串惦银。
flag: 用flag代表操作行為咆课。可以參考下圖扯俱!
mode: mode代表文件的權(quán)限书蚪,預(yù)設(shè)為0666代表可讀可寫(xiě)。
call back: 是帶兩個(gè)參數(shù)的function迅栅,err及file data殊校,當(dāng)我們執(zhí)行open完成時(shí), 要做的事, 例如: 打開(kāi)成功的訊息顯示;失敗時(shí)库继,丟出err箩艺。
開(kāi)啟讀取檔案
fs.read(fd, buffer, offset, length, position, callback)
fd: 透過(guò)fs.open() 方法返回的文件描述符。
buffer: 數(shù)據(jù)寫(xiě)入的緩沖區(qū)宪萄。
offset: 緩沖區(qū)寫(xiě)入的寫(xiě)入偏移量艺谆。
length: 要從文件中讀取的字元數(shù)。
position: 文件讀取的起始位置拜英,如果position 的值為null静汤,則會(huì)從當(dāng)前文件游標(biāo)的位置讀取。
callback:回呼函式居凶,有三個(gè)參數(shù)err, bytesRead, buffer虫给。
err為錯(cuò)誤訊息, bytesRead表示讀取的字元數(shù)侠碧,buffer為緩沖區(qū)對(duì)象
關(guān)閉
fs.close(fd, callback)
fd:透過(guò)fs.open()方法返回的文件描述符抹估。
call back:只帶一個(gè)錯(cuò)誤參數(shù)err的function,當(dāng)我們執(zhí)行close完成時(shí),要做的事弄兜。例如:失敗時(shí)药蜻,丟出err瓷式。
刪除文件
fs.unlink(path, callback);刪除存在的文件。
path:檔案路徑语泽。
callback:只帶一個(gè)錯(cuò)誤參數(shù)err的function贸典,當(dāng)我們執(zhí)行unlink完成時(shí),要做的事。例如:刪除成功的訊息顯示踱卵;失敗時(shí)廊驼,丟出err。
更多資訊:https://nodejs.org/dist/latest-v8.x/docs/api/readline.html
代碼調(diào)試工具(主要推薦阮一峰介紹的調(diào)試工具)
Node.js 內(nèi)建的debugger
1惋砂、進(jìn)入command prompt 執(zhí)行debugger
node inspect orfile.js
2妒挎、此時(shí),可以看到程式進(jìn)入debugging 模式班利。你可以看到>符號(hào)饥漫,指向目前debugging 的程式行
3榨呆、.我們可以再在debug>輸入next (或n)罗标,debugging下一個(gè)程式區(qū)段
4、如果我們想要執(zhí)行到下一個(gè)debugger; 积蜻,則在debug>輸入 cont (或c)
設(shè)定中斷點(diǎn)break-point
setBreakpoint(), sb() – 設(shè)定中斷點(diǎn)于目前所在行數(shù)
setBreakpoint(line), sb(line) – 設(shè)定中斷點(diǎn)給特定行數(shù)
setBreakpoint(‘fn()’), sb(…) – 設(shè)定中斷點(diǎn)在函式的第一句
setBreakpoint(‘script.js’, 1), sb(…)– 設(shè)定中斷點(diǎn),在指定檔名的第一行闯割。(用于程式中有載入別的檔案時(shí))
clearBreakpoint(‘script.js’, 1), cb(…)– 清除中斷點(diǎn),在指定檔名的第一行。(用于程式中有載入別的檔案時(shí))
watch, watchers
在debug過(guò)程中竿拆,想要查看一些資訊宙拉,例如,變數(shù)/參數(shù)…丙笋,可以用watch(“exp")
刪除某項(xiàng)watch資訊谢澈,則,可用 unwatch(“exp")
常用的內(nèi)建debug指令:
next, n執(zhí)行至下一行御板。
cont, c繼續(xù)執(zhí)行并停在下一個(gè)debuggers;
step, s進(jìn)入函式逐一除錯(cuò)锥忿。
out Step, o跳出函式的逐一除錯(cuò)。
watch加入表示式及變數(shù)至watch
watcher查看所有被加入的watch的值怠肋。
Pause暫停執(zhí)行程式敬鬓。
更多資訊:
http://www.ruanyifeng.com/blog/2018/03/node-debugger.html
https://nodejs.org/dist/latest-v8.x/docs/api/inspector.html
事件監(jiān)聽(tīng)
自定觸發(fā)及監(jiān)聽(tīng)函式
Javascript 事件綁定通常使用addlistener,通常觸發(fā)事件范圍會(huì)有限笙各,像通常使用的事件綁定钉答,click, hover, focus, blur..
eventEmitter:自定義事件觸發(fā)
事件名稱(chēng)可以任意取名,通常我們用駝峰式命名法杈抢,但也不限定
函式可以被附加在這個(gè)物件数尿,當(dāng)物件被執(zhí)行時(shí),觸發(fā)這個(gè)函式惶楼,這些函式叫監(jiān)聽(tīng)函式
// get the reference of EventEmitter class of events module
var events=require('events');
//create an object of EventEmitter class by using above reference.
var em=new events.EventEmitter();
//綁定事件函式
em.on('FirstEvent',function(data){
console.log('First subscriber:'+data);
});
//emit觸發(fā)事件
em.emit('FirstEvent','我已經(jīng)進(jìn)入了第一事件的監(jiān)聽(tīng)函式!');
上述例子右蹦,我們先建立一個(gè)events.EventEmitter 物件虏缸,叫做em,然后嫩实,我們?cè)俳壎ㄊ录幚砗接胦n()刽辙,最后用emit觸發(fā)事件
addListener()的方法,去自訂觸發(fā)事件:
var emitter=require('events').EventEmitter;
var em=new emitter();
em.addListener('FirstEvent',function(data){
console.log('First Scriber: '+data);
});
em.on('SecondEvent',function(data){
console.log('Second Scriber:'+data);
});
em.emit('FirstEvent',"這是第一個(gè)監(jiān)聽(tīng)式!");
em.emit('SecondEvent',"這是第二個(gè)監(jiān)聽(tīng)式!");
有二種EventEmitter 使用上的常見(jiàn)模式:從函式return EventEmitter 物件;繼承EventEmitter 類(lèi)別
從函式回傳EventEmitter物件(也就是emit可以寫(xiě)在function里)
var emitter=require('events').EventEmitter;
function LoopProcessor(num){
var e = new emitter();
setTimeout(function(){
for(var i=1;i<=num;i++){
e.emit('BeforeProcess',i);
console.log('Processing number : '+i);
e.emit('AfterProcess',i);
}
},2000);
return e;
}
var lp=LoopProcessor(3);
lp.on('BeforeProcess',function(data){
console.log('About to start the process for '+data);
});
lp.on('AfterProcess',function(data){
console.log('Completed processing '+data);
});
執(zhí)行結(jié)果:
繼承EventEmitter 類(lèi)別(我們可以用util.inherits()甲献,它是utility module的方法宰缤,所以,一開(kāi)始就必須用require(‘util’)載入該模組)
var emitter = require('events').EventEmitter;
//繼承時(shí), 需要用到的模組
var util = require('util');
function LoopProcessor(num) {
var me = this;
setTimeout(function () {
for (var i = 1; i <= num; i++) {
me.emit('BeforeProcess', i);
console.log('Processing number:' + i);
me.emit('AfterProcess', i);
}
}
, 2000)
return this;
}
//直接讓LoopProcessor 繼承 emitter 類(lèi)別
util.inherits(LoopProcessor, emitter)
var lp = new LoopProcessor(3);
lp.on('BeforeProcess', function (data) {
console.log('About to start the process for ' + data);
});
lp.on('AfterProcess', function (data) {
console.log('Completed processing ' + data);
});