以前學(xué)習(xí)C疚漆、OC、Swift、H5的時候都沒有留下痕跡娶聘,心里甚是遺憾闻镶,最近用Nodejs參與了一個web開發(fā),果斷留個紀(jì)念丸升,供日后瞻仰铆农。。狡耻。
菜鳥教程:http://www.runoob.com/nodejs/nodejs-install-setup.html
Github:https://github.com/Zyj163/Node.JS_learning(筆記墩剖,非demo)
環(huán)境配置:
方式一:http://nodejs.org下載安裝(我用的這個)
方式二:使用終端(網(wǎng)上介紹的,沒實驗夷狰。岭皂。。)
1.安裝home-brew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)
2.安裝node
brew install node
當(dāng)安裝Node時會同時安裝npm沼头,npm是Node開發(fā)包管理器爷绘,用法省略。进倍。土至。
使用:
先來一個Hello World
創(chuàng)建一個helloWorld.js的文件(我用的編輯器是webStorm)
var http = require('http');
http.createServer(function(req,res){
// 發(fā)送 HTTP 頭部
// HTTP 狀態(tài)值: 200 : OK
// 內(nèi)容類型: text/plain
? ? ? ? res.writeHead(200, { 'Content-Type': 'text/plain' });
// 發(fā)送響應(yīng)數(shù)據(jù) "Hello World"
? ? ? ? res.end('Hello world!');
}).listen(3000);
console.log('Server started on localhost:3000; press Ctrl-C to terminate....');
打開終端,cd到當(dāng)前目錄猾昆,node hello World.js陶因,然后打開瀏覽器訪問http://localhost:3000即可
推薦一個好東西sudo npm install -g supervisor,cd到當(dāng)前目錄supervisor helloWorld.js毡庆,這樣就不需要每次修改后臺代碼后坑赡,重啟服務(wù)了,退出Ctrl+c
Node.js 是單進(jìn)程單線程應(yīng)用程序么抗,但是通過事件和回調(diào)支持并發(fā),所以性能非常高亚铁。Node 所有 API 都支持回調(diào)函數(shù)蝇刀。
Node.js 的每一個 API 都是異步的,并作為一個獨立線程運行徘溢,使用異步函數(shù)調(diào)用吞琐,并處理并發(fā)。
Node.js 基本上所有的事件機(jī)制都是用設(shè)計模式中觀察者模式實現(xiàn)然爆。
Node.js 單線程類似進(jìn)入一個while(true)的事件循環(huán)站粟,直到?jīng)]有事件觀察者退出,每個異步事件都生成一個事件觀察者曾雕,如果有事件發(fā)生就調(diào)用該回調(diào)函數(shù).
Node.js 使用事件驅(qū)動模型奴烙,當(dāng)web server接收到請求,就把它關(guān)閉然后進(jìn)行處理,然后去服務(wù)下一個web請求切诀。當(dāng)這個請求完成揩环,它被放回處理隊列,當(dāng)?shù)竭_(dá)隊列開頭幅虑,這個結(jié)果被返回給用戶丰滑。引用runoob中的一張圖
EventEmitter
Node.js 有多個內(nèi)置的事件,我們可以通過引入 events 模塊倒庵,并通過實例化 EventEmitter 類來綁定和監(jiān)聽事件
// 引入 events 模塊
var events = require('events');
// 創(chuàng)建 eventEmitter 對象
var eventEmitter = new events.EventEmitter();
// 綁定事件及事件的處理程序
eventEmitter.on('eventName', eventHandler);
// 觸發(fā)事件
eventEmitter.emit('eventName','arg1','arg2');
//移除指定事件的一個已經(jīng)注冊的監(jiān)聽器
eventEmitter.removeListener('eventName',eventHandler);
//移除指定事件的所有監(jiān)聽器
eventEmitter.removeAllListeners('eventName');
EventEmitter 對象如果在實例化時發(fā)生錯誤褒墨,會觸發(fā) 'error' 事件。當(dāng)添加新的監(jiān)聽器時擎宝,'newListener' 事件會觸發(fā)貌亭,當(dāng)監(jiān)聽器被移除時,'removeListener' 事件被觸發(fā)认臊∑酝ィ可以給同一事件創(chuàng)建多個監(jiān)聽,會被先后調(diào)用。
大多數(shù)時候我們不會直接使用 EventEmitter失晴,而是在對象中繼承它剧腻。 包括 fs、net涂屁、 http 在內(nèi)的书在,只要是支持事件響應(yīng)的核心模塊都是 EventEmitter 的子類。
Buffer(緩沖區(qū))
在 Node.js 中拆又,Buffer 類是隨 Node 內(nèi)核一起發(fā)布的核心庫儒旬。Buffer 庫為 Node.js 帶來了一種存儲原始數(shù)據(jù)的方法,可以讓 Node.js 處理二進(jìn)制數(shù)據(jù)帖族,每當(dāng)需要在 Node.js 中處理I/O操作中移動的數(shù)據(jù)時栈源,就有可能使用 Buffer 庫。原始數(shù)據(jù)存儲在 Buffer 類的實例中竖般。一個 Buffer 類似于一個整數(shù)數(shù)組甚垦,但它對應(yīng)于 V8 堆內(nèi)存之外的一塊原始內(nèi)存。
//方法 1
//創(chuàng)建長度為 10 字節(jié)的 Buffer 實例:
var buf=newBuffer(10);
//方法 2
//通過給定的數(shù)組創(chuàng)建 Buffer 實例:
var buf2=newBuffer([10,20,30,40]);
//方法 3
//通過一個字符串來創(chuàng)建 Buffer 實例:
var buf3=newBuffer("www.runoob.com","utf-8");
/*寫入
buf.write(string[, offset[, length]][, encoding])
參數(shù)
參數(shù)描述如下:
string - 寫入緩沖區(qū)的字符串涣雕。
offset - 緩沖區(qū)開始寫入的索引值艰亮,默認(rèn)為 0 。
length - 寫入的字節(jié)數(shù)挣郭,默認(rèn)為 buffer.length
encoding - 使用的編碼迄埃。默認(rèn)為 'utf8' 。
* */
var len=buf.write('www.runoob.com');
console.log('寫入字節(jié)數(shù):'+len);
/*讀取
buf.toString([encoding[, start[, end]]])
參數(shù)
參數(shù)描述如下:
encoding - 使用的編碼兑障。默認(rèn)為 'utf8' 侄非。
start - 指定開始讀取的索引位置蕉汪,默認(rèn)為 0。
end - 結(jié)束位置彩库,默認(rèn)為緩沖區(qū)的末尾肤无。
* */
var re=buf.toString();
//轉(zhuǎn)為json對象
var json=buf.toJSON(buf);
//合并buffer
var buf4= Buffer.concat([buf,buf3]);
/*拷貝
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
參數(shù)
參數(shù)描述如下:
targetBuffer - 要拷貝的 Buffer 對象。
targetStart - 數(shù)字, 可選, 默認(rèn): 0
sourceStart - 數(shù)字, 可選, 默認(rèn): 0
sourceEnd - 數(shù)字, 可選, 默認(rèn): buffer.length
* */
var buf5=newBuffer(10);
buf5.copy(but);
Stream(流)
Stream 對象都是 EventEmitter 的實例(對http 服務(wù)器發(fā)起請求的request 對象就是一個 Stream骇钦,所以request也有下面的事件)宛渐。常用的事件有:
data - 當(dāng)有數(shù)據(jù)可讀時觸發(fā)。
end - 沒有更多的數(shù)據(jù)可讀時觸發(fā)眯搭。
error - 在接收和寫入過程中發(fā)生錯誤時觸發(fā)窥翩。
finish - 所有數(shù)據(jù)已被寫入到底層系統(tǒng)時觸發(fā)。
從流中讀數(shù)據(jù):
var fs = require("fs");
var data = '';
// 創(chuàng)建可讀流
var readerStream = fs.createReadStream('input.txt');
// 設(shè)置編碼為 utf8鳞仙。
readerStream.setEncoding('UTF8');
// 處理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
data += chunk;
});
readerStream.on('end',function(){
console.log(data);
});
readerStream.on('error', function(err){
console.log(err.stack);
});
寫入流:
var fs = require("fs");
var data = '菜鳥教程官網(wǎng)地址:www.runoob.com';
// 創(chuàng)建一個可以寫入的流寇蚊,寫入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 編碼寫入數(shù)據(jù)
writerStream.write(data,'UTF8');
// 標(biāo)記文件末尾
writerStream.end();
// 處理流事件 --> data, end, and error
writerStream.on('finish', function() {
console.log("寫入完成。");
});
writerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序執(zhí)行完畢");
管道流:
var fs= require('fs')
var zlib= require('zlib')
//壓縮
fs.createReadStream('input.txt')
? ?.pipe(zlib.createGzip())
? ?.pipe(fs.createWriteStream('input.zip'))
//解壓
fs.createReadStream('input.zip')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('input.txt'))
模塊系統(tǒng):
1棍好、提供函數(shù):
定義:
exports.world = function() {}
使用:
var use = require('./world');
use.world();
2仗岸、提供對象:
定義:(fuc外面的東西可以理解為私有的,里面的是公開的)
function Hello() {
? ? ? ? ? ? ? var name;
? ? ? ? ? ? ? this.setName = function(thyName) {
? ? ? ? ? ? ? ? ? ? ? ? ?name = thyName;
? ? ? ? ? ? ? };
? ? ? ? ? ? ? this.sayHello = function() {
? ? ? ? ? ? ? ? ? ? ? ? console.log('Hello ' + name);
? ? ? ? ? ? ? };
};
module.exports = Hello;
使用:
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
路由:
解析URL借笙,引用url和querystring模塊
全局對象與全局變量:
__filename 表示當(dāng)前正在執(zhí)行的腳本的文件名扒怖。它將輸出文件所在位置的絕對路徑,且和命令行參數(shù)所指定的文件名不一定相同业稼。 如果在模塊中盗痒,返回的值是模塊文件的路徑。
__dirname 表示當(dāng)前執(zhí)行腳本所在的目錄低散。
process.memoryUsage() 輸出內(nèi)存使用情況
常用工具:
util.inherits(constructor, superConstructor)是一個實現(xiàn)對象間原型繼承 的函數(shù)俯邓。JavaScript 的面向?qū)ο筇匦允腔谠偷模c常見的基于類的不同熔号。JavaScript 沒有 提供對象繼承的語言級別特性稽鞭,而是通過原型復(fù)制來實現(xiàn)的。
var util= require('util');
functionBase(){
//不能繼承
this.name='base';
this.base=1991;
this.sayHello=function(){
console.log('hello'+this.name);
}
}
//可以被繼承
Base.prototype.showName=function(){
console.log(this.name);
};
functionSub(){
this.name='sub';
//Sub 僅僅繼承了Base 在原型中定義的函數(shù)跨嘉,而構(gòu)造函數(shù)內(nèi)部創(chuàng)造的 base 屬 性和 sayHello 函數(shù)都沒有被 Sub 繼承川慌。
}
util.inherits(Sub,Base);
varobjBase=newBase();
objBase.showName();
objBase.sayHello();
console.log(objBase);
varobjSub=newSub();
objSub.showName();
console.log(objSub);
util.inspect(object,[showHidden],[depth],[colors])是一個將任意對象轉(zhuǎn)換 為字符串的方法,通常用于調(diào)試和錯誤輸出祠乃。它至少接受一個參數(shù) object,即要轉(zhuǎn)換的對象兑燥。
更多詳情可以訪問 http://nodejs.org/api/util.html 了解詳細(xì)內(nèi)容
可以使用typeof some ==='function' 做類型判斷
文件系統(tǒng):
應(yīng)該很多都需要知道亮瓷,沒必要截了http://www.runoob.com/nodejs/nodejs-fs.html
知道這些基礎(chǔ)知識差不多就可以進(jìn)行下一個目標(biāo)express了,這個才是重點=低嘱支!