1. 程式人生 > 程式設計 >node.js 如何監視檔案變化

node.js 如何監視檔案變化

fs.FSWatcher

fs.FSWatcher類 繼承了 EventEmitter,用於監視檔案變化,呼叫 fs.watch 後返回一個 fs.FSWatcher 例項,每當指定監視的檔案被修改時,例項會觸發事件呼叫回撥函式

fs.watch('./tmp',(eventType,filename) => {
 if (filename) {
  console.log(filename);
 }
});

fs.watch()

fs.watch(filename[,options][,listener]) 監視檔案變化,返回 fs.FSWatcher 例項

1.filename:檔案或資料夾路徑

2.options

  • encoding
  • recursive:預設值 false,應該監視所有子目錄,還是僅監視當前目錄,僅在 macOS 和 Windows 上支援
  • persistent:預設值 true,指示如果檔案已正被監視,程序是否應繼續執行
  • listener(eventType,filename):檔案變化回撥函式

eventType 主要是 renamechange ,在大多數平臺上,檔案在目錄中出現或消失時觸發 'rename' 事件,在 Windows 上,如果監視的目錄被移動或重新命名,則不會觸發任何事件,當監視的目錄被刪除時,則報告 EPERM

錯誤

fs.watch('./',{ recursive: true },filename) => {
 console.log(eventType,filename);
});

fs.watchFile()

fs.watchFile(filename[,options],listener) 用於監視檔案變化

1.filename

2.options

  • biginit:預設值 false,指定回撥 stat 中的數值是否為 biginit 型別
  • persistent:預設值 true,當檔案正在被監視時,程序是否應該繼續執行
  • interval:預設值 5007,用來指定輪詢頻率(ms)

3.listener(currentStats,previousStats):listener 有兩個引數,當前的 stat 物件和之前的 stat 物件
要在修改檔案時收到通知,則需要比較 curr.mtime prev.mtime

const fs = require('fs');

fs.watchFile('./test.txt',{ interval: 100 },(curr,prev) => {
 console.log('當前的最近修改時間是: ' + curr.mtime);
 console.log('之前的最近修改時間是: ' + prev.mtime);
});

const tid = setInterval(() => {
 fs.appendFile('./test.txt','Hello,world!\n',err => {
  if (err) throw err;
  console.log('檔案修改完成');
 });
},300);

setTimeout(() => {
 clearInterval(tid);
 fs.unwatchFile('./test.txt');
},2000);

fs.watch() 與 fs.watchFile()

因為 fs.watchFile() 使用輪訓方式檢測檔案變化,如果不設定 interval 或者設定較高的值會發現檔案變化的監視有延遲
而 fs.watch() 監聽作業系統提供的事件,而且可以監視目錄變化,使用 fs.watch() 比 fs.watchFile() 更高效,平常應儘可能使用 fs.watch() 代替 fs.watchFile()

當然 fs.watch() 依賴作業系統的實現,在不同平臺上表現會有差異

  • Linux 作業系統使用 inotify
  • 在 macOS 系統使用 FSEvents
  • 在 windows 系統使用 ReadDirectoryChangesW

fs.unwatchFile

fs.unwatchFile(filename[,listener]) 停止監視 filename 的變化,如果指定了 listener,則僅移除此特定監聽器,否則將移除所有監聽器,從而停止監視 filename

fs.unwatchFile('./test.txt');

社群選擇

fs.watchFile() 效能問題,fs.watch() 平臺不一致等兩個方法都有不盡如人意的地方

Node.js fs.watch:

MacOS 有時候不提供 filename
在部分場景不觸發修改事件(MacOS Sublime)
經常一次修改兩次觸發事件
大部分檔案變化 eventType 都是 rename.
未提供簡單的監視檔案樹方式

Node.js fs.watchFile:

事件處理問題和 fs.watch 一樣爛
沒有巢狀監聽
CPU 消耗大

https://www.npmjs.com/package/chokidar

日常在監視檔案變化可以選擇社群的優秀方案

  1. node-watch
  2. chokidar
const chokidar = require('chokidar');
 
// One-liner for current directory
chokidar.watch('.').on('all',(event,path) => {
 console.log(event,path);
});
// Initialize watcher.
const watcher = chokidar.watch('file,dir,glob,or array',{
 ignored: /(^|[\/\\])\../,// ignore dotfiles
 persistent: true
});
 
// Something to use when events are received.
const log = console.log.bind(console);
// Add event listeners.
watcher
 .on('add',path => log(`File ${path} has been added`))
 .on('change',path => log(`File ${path} has been changed`))
 .on('unlink',path => log(`File ${path} has been removed`));
 
// More possible events.
watcher
 .on('addDir',path => log(`Directory ${path} has been added`))
 .on('unlinkDir',path => log(`Directory ${path} has been removed`))
 .on('error',error => log(`Watcher error: ${error}`))
 .on('ready',() => log('Initial scan complete. Ready for changes'))
 .on('raw',path,details) => { // internal
  log('Raw event info:',event,details);
 });

以上就是node.js 如何監視檔案變化的詳細內容,更多關於node.js 監視檔案的資料請關注我們其它相關文章!