《node.js權威指南》讀書筆記

第一章 node.js介紹

非阻塞型I/O機制

當在訪問數據庫取得搜索結果的時候,在開始訪問數據庫以後,數據庫返回結果以前,存在一段等待時間。
在傳統的單線程處理機制中,在執行了訪問數據庫的代碼以後,整個線程都將暫停下來,等待數據庫返回查詢結果以後才能繼續執行後面的代碼。這是I/O型阻塞
node.js中在執行了訪問數據庫的代碼以後將當即執行其後面的代碼段,把數據庫返回的結果的處理代碼放在回調函數中。這是非阻塞型I/O機制html

第三章 node.js中的全局做用域及全局函數

timer.unref()用於取消setTimeout或setInterval函數中指定的回調函數的調用
timer.ref()恢復unref方法取消的回調函數node

var testFunction = function(){
    console.log('aaa')
}
var timer = setInterval(testFunction,3000)
//取消定時器對象的回調函數調用
timer.unref() //沒有輸出
//恢復定時器對象的回調函數調用
// timer.ref()//有輸出

在任何模塊文件內部,可使用__filename變量獲取當前模塊文件名
在任何模塊文件內部,可使用__dirname變量獲取當前模塊文件所在目錄的完成絕對路徑數據庫

EventEmitter類

emitter.setMaxListeners(n)
默認狀況下,若是爲特定事件添加了超過 10 個監聽器,則 EventEmitter 會打印一個警告
emitter.setMaxListeners() 方法能夠爲指定的 EventEmitter 實例修改限制。 值設爲 Infinity(或 0)表示不限制監聽器的數量。編程

當須要手工觸發某個對象的一個事件時,使用EventEmitter類的emit方法
emitter.emit(event,[arg1],...)windows

第六章 在Node.js中操做文件系統

在node.js中使用fs模塊來實現全部有關文件及目錄的建立寫入及刪除操做,全部的操做都有同步(有Sync後綴)和異步的方法緩存

文件的完整讀寫

fs.readFile(path,[options],callback)
options參數爲一個對象,在該參數值對象中可使用flag屬性指定對該文件採起什麼操做,默認是‘r’
可指定值以下所示

在options參數值中可以使用encoding屬性指定使用何種編碼格式來讀取該文件,可指定‘utf8’,'ascii','base64'app

var fs = require('fs')
fs.readFile('./test.txt',utf8',function(err,data){
    if(err){
        console.log('read error')
    }else{
        coonsole.log(data.toString())    //將buffer對象轉換爲字符串
    }
})

fs.writeFile(path,data,[options],callback)
data參數用於指定須要寫入的內容,能夠是一個字符串或一個buffer對象
options參數值爲一個對象dom

var options= {
    flag:'w' //用於指定對該文件採起何種操做,默認'w'
    mode:0666 //用於指定當文件被打開時對該文件的讀寫權限,默認0666(可讀寫)
    encoding:'utf8'//用於指定使用何種編碼格式來寫入該文件
}
var fs = require('fs')
fs.writeFile('./message.txt','這是第一行\r\n這是第二行',function(err){
    if(err){
        console.log('err:',err)
    }else{
        console.log('success')
    }
})

將一個字符串或一個緩衝區的數據追加到一個文件底部時,可使用fs.appendFile()或者fs.appendFileSync()異步

var fs = require('fs')
fs.appendFile('./message.txt','\r\n這是追加的數據',function(err){
    if(err){
        console.log('err:',err)
    }else{
        console.log('success')
    }
})

從指定位置處開始讀寫文件

首先須要使用fs模塊中的open方法或者openSync方法打開文件
fs.open(path,flags,[model],callback)函數

var fs = require('fs')

fs.open('./message.txt','r',function(err,fd){
    if(err){
        console.log('err:',err)
    }else{
        console.log(fd)//文件描述符
    }
})

打開文件後能夠在回調函數中使用fs.read()從文件指定位置處讀取文件,也可使用fs.write()方法從文件的指定處開始寫入數據
read()從文件的指定位置出讀取文件,一直讀取到文件底部而後將讀取到的內容輸出到一個緩衝區

fs.read(fd,buffer,offset,length,position,callback)

fd參數值必須爲open方法所使用的回調函數中返回的文件描述符
offset參數用於指定向緩存區中寫入數據的開始寫入位置(以字節爲單位)
length參數用於指定從文件中讀取的字節數
position參數用於指定讀取文件時的開始位置

fs.open('./message.txt','r',function (err,fd) {
    var buf = new Buffer(255)
    fs.read(fd,buf,0,9,3,function (err,bytesRead,buffer) {
        console.log(buffer.slice(0,bytesRead).toString())
    })
})

再打開文件以後,可使用fs.write()或者writeSync()方法從一個緩存區中讀取數據而且從文件的指定出開始寫入數據
fs.write(fd,buffer,offset,length,position,callback)
參數與open方法參數相似

var buf = new Buffer('我喜好編程')
fs.open('./message.txt','w',function (err,fd) {
    fs.write(fd,buf,3,9,0,function (err,written,buffer) {
        if(err){
            console.log(err)
        }
        console.log('success')
    })
})

在fs模塊中提供close()與closeSync()關閉文件
fs.close(fd,[callback])
在使用write()方法在文件中寫入數據時,操做系統先將該部分數據讀取到內存中,在把數據寫入到文件中,當數據讀完並不表明數據已經寫入,此時調用close()方法會將部分數據丟失。
咱們須要調用fs.fsync方法對文件進行同步操做

var buf = new Buffer('我喜好編程')
fs.open('./message.txt','a',function (err,fd) {
    fs.write(fd,buf,12,3,null,function (err,written,buffer) {
        if(err){
            console.log(err)
        }
        console.log('success')
        fs.fsync(fd)
        fs.close(fd)
    })
})

建立與讀取目錄

fs.mkdir(path,[mode],callback)建立目錄
mode參數值用於指定該目錄的權限,默認值0777

fs.mkdir('./test',function (err) {
    if(err){
        console.log(err)
    }else{
        console.log('success')
    }
})

fs.readdir(path,callback) 讀取目錄

fs.readdir('./',function (err,files) {
    if(err){
        console.log(err)
    }else{
        console.log(files)
    }
})

查看與修改文件或目錄的信息

在fs模塊中,可使用stat方法或lstat方法查看一個文件或目錄的信息,區別是當查看符號連接文件時必須使用lstat()
fs.stat(path,callback)

fs.stat('./message.txt',function (err,stats) {
    console.log(stats)
})

stats對象擁有如下屬性和方法



在使用open方法打開文件並返回文件描述符後可使用fs.fstat()查看文件信息
fs.fstat(fd,callback)

檢查文件是否存在

fs.access(path[, mode], callback)
mode 默認爲 fs.constants.F_OK。

fs.access(file, (err) => {
  console.log(`${file} ${err ? '不存在' : '存在'}`);
});

獲取文件或目錄的絕對路徑

fs.realpath(path[, options], callback)

fs.realpath('./message.txt',function (err,resolvedPath) {
    if(err)throw err
    console.log(resolvedPath)
})

修改文件訪問時間及修改時間

fs.utimes(path, atime, mtime, callback)
atime參數用於指定修改後的訪問時間
mtime參數用於指定修改後的修改時間

let file = './message.txt';
fs.utimes(file,new Date(),new Date(),function (err) {
    if(err)console.log(err)
    console.log('success')
})

在open方法打開的文件並返回文件描述符後可使用fs.futimes()修改文件的修改時間或訪問時間
fs.futimes(fd,atime,mtime,callback)

修改文件或目錄的讀寫權限

fs.chmod(path, mode, callback)

let file = './message.txt';
fs.chmod(file,0755,function (err) {
    if(err)console.log(err)
    else console.log('success')
})

移動文件或目錄

fs.rename(oldPath, newPath, callback)

fs.rename('舊文件.txt', '新文件.txt', (err) => {
  if (err) throw err;
  console.log('已完成重命名');
});

建立與刪除文件的硬連接

可使用link方法建立文件的硬連接(表面上是兩份文件,實際上是一份文件,修改一個會影響其餘)
fs.link(srcpath,dstpath,callback)
srcpath用於指定須要被建立硬連接的文件的完整路徑及文件名
dstpath用於指定被建立的硬連接的完整路徑及文件名

let file = "./message.txt";
fs.link(file, "./test/test.txt", function(err) {
    if (err) console.log(err);
    else console.log("success");
});

刪除硬連接
fs.ulink(path,callback)

建立與查看符號連接

可使用fs.symlink方法來建立文件或目錄的符號連接
fs.symlink(srcpath, dstpath,[type], callback)
srcpath用於指定須要被建立符號連接的文件的完整路徑及文件名
dstpath用於指定被建立的符號連接的完整路徑及文件名
type參數用於指定爲文件建立符號連接仍是目錄連接,默認file
file:文件建立符號連接
dir目錄建立符號連接(junction:windows系統中的目錄建立符號連接)

fs.symlink('./a','./b','dir',function(err){
    if(err){
        console.log(err)
    }else{
        fs.symlink(__dirname+'/a/test.txt',__dirname+'/b/anotherMessage.txt','file',function (err) {
            if(err)console.log(err)
            else console.log('success')
        })
    }
})

readlink方法用於讀取符號連接中所包含的另外一個文件或目錄的路徑及文件名操做
fs.readlink(path,callback)

截斷文件

fs.trunkcate(filename,len,callback)
len參數值爲一個整數,用於指定須要被截斷後的文件尺寸

let file = './message.txt';
fs.truncate(file,9,function(err){
    if(err){
        console.log(err)
    }else{
        fs.stat(file,function(err,stats){
            console.log(stats.size)
        })

    }
})

刪除空目錄

fs.rmdir(path,callback)

監視文件或目錄

fs.watchFile(filename[, options], listener)
監視 filename 的變化。 每當文件被訪問時會調用 listener。
options 對象能夠有一個布爾值的 persistent 屬性,代表當文件正在被監視時,進程是否繼續運行。
options 對象能夠指定一個 interval 屬性,指定目標每隔多少毫秒被輪詢。 默認值爲 { persistent: true, interval: 5007 }。
listener 有兩個參數,當前的狀態對象curr和之前的狀態對象prev:

let file = './message.txt';
fs.watchFile(file,function(curr,prev){
    if(Date.parse(prev.ctime)==0){
        console.log('文件被建立')
    }else if(Date.parse(curr.ctime)==0){
        console.log('文件被刪除')
    }else if(Date.parse(prev.mtime)!==Date.parse(curr.mtime)){
        console.log('文件被修改')
    }
})

能夠用unwatchFile()取消當前文件發生變化時所要執行的處理
fs.unwatchFile(filename,[listener])
可使用watch()方法對文件或目錄進行監視變化並執行某些處理
var watcher = fs.watch(filename,[options],[listener])
listener 有兩個參數 (eventType, filename)。 eventType 多是 'rename' 或 'change',filename 是觸發事件的文件名。

let file = './message.txt';
var watcher= fs.watch(file,function(event,filename){
    console.log(event)
    console.log(filename)
    watcher.close()//中止監控
})

使用ReadStream對象讀取文件

fs.createReadStream(path,[options])
options參數爲一個對象可以使用的屬性以下

var file = fs.createReadStream('./message.txt',{start:3,end:12})
file.on('open',function(fd){//開始讀取數據
    console.log('start')
})
file.on('data',function(data){//讀取到數據
    console.log('read',data.toString())
})
file.on('end',function(){//讀取完畢
    console.log('end')
})
file.on("close", function() {//文件關閉
    console.log("close");
});
file.on("error", function() {//讀取失敗
    console.log("error");
});
file.pause()//暫停讀取
file.sume()//恢復讀取

使用writeStream對象寫入文件

fs.createWriteStream(path,[options])
options對象屬性
flags 詳見支持的 flag。默認爲 'w'。
encoding 默認爲 'utf8'。
fd 默認爲 null。文件描述符。
mode 默認爲 0o666。
autoClose 默認爲 true。
start 開始寫入位置

對路徑進行操做

path.normalize(path)

var fs = require("fs");
var path = require("path");
var myPath = path.normalize(".//a//b//c/e");
console.log(myPath);// a/b/c/e

path.join([...paths])
使用平臺特定的分隔符把全部 path 片斷鏈接到一塊兒,並規範化生成的路徑

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); // '/foo/bar/baz/asdf'

path.resolve([...paths])
將路徑或路徑片斷處理成絕對路徑。

var path = require('path')
var myPath = path.resolve('a','b','c')

path.dirname(p)
獲取路徑中的目錄名
當參數爲目錄路徑時,該方法返回該目錄的上層目錄
當參數爲文件路徑時,該方法返回該文件所在目錄
path.basename(p,[ext])
用於獲取一個路徑中的文件名

path.basename('./foo/bar/baz/index.html','.html')// index

extname()獲取一個路徑中的擴展名
path.extname(p)
path.sep屬性爲操做系統的文件分隔符
path.delimiter屬性爲操做系統指定的路徑分隔符

第10章 Node.js中的錯誤處理與斷言處理

在js中雖然可使用try...catch機制來捕捉同步方法中拋出的錯誤,可是不能使用try...catch機制來捕捉異步方法中拋出的錯誤

建立並使用domain對象

var domain = domain.create()

當該對象捕捉到任何錯誤時,觸發該對象的error事件,

var domain=require('domain');
var fs=require('fs');
var d = domain.create();
d.name='d1';
d.on('error', function(err) {
    console.error('%s捕獲到錯誤!',d.name,err);
});
d.run(function() {
    process.nextTick(function() {
        setTimeout(function() { //模擬一個回調函數
            fs.open('non-existent file', 'r', function(err, fd) {
                if (err) throw err;
            });
        }, 1000);
    });
});

綁定回調函數與攔截回調函數

domain.bind(),將回調函數與domain對象進行綁定,從而捕捉回調函數的錯誤

var fs=require('fs');
var domain = require('domain');
var d = domain.create();
fs.readFile('./test.txt',d.bind(function(err, data) {
    if(err) throw err;
    else console.log(data);
}));
d.on('error', function(err) {
    console.log('讀取文件時發生如下錯誤:');
    console.log(err);
});

domain,intercept()方法攔截一個回調函數中的錯誤,該方法與bind的區別在於回調函數中必須使用throw關鍵字拋出錯誤

var fs=require('fs');
var domain = require('domain');
var d = domain.create();
fs.readFile('./test.txt',d.intercept(function(err, data) {
    console.log(data);
}));
d.on('error', function(err) {
    console.log('讀取文件時發生如下錯誤:');
    console.log(err);
});
相關文章
相關標籤/搜索