极简 Node.js 入门 - 3.5 监视文件变化
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node
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 实例
- filename:文件或文件夹路径
- options
- encoding
- recursive:默认值 false,应该监视所有子目录,还是仅监视当前目录,仅在 macOS 和 Windows 上支持
- persistent:默认值 true,指示如果文件已正被监视,进程是否应继续运行
- listener(eventType, filename):文件变化回调函数
eventType 主要是 rename
和 change
,在大多数平台上,文件在目录中出现或消失时触发 'rename' 事件,在 Windows 上,如果监视的目录被移动或重命名,则不会触发任何事件,当监视的目录被删除时,则报告 EPERM
错误
fs.watch('./', { recursive: true }, (eventType, filename) => {
console.log(eventType, filename);
});
fs.watchFile()
fs.watchFile(filename[, options], listener)
用于监视文件变化
- filename
- options
- biginit:默认值 false,指定回调 stat 中的数值是否为 biginit 类型
- persistent:默认值 true,当文件正在被监视时,进程是否应该继续运行
- interval:默认值 5007,用来指定轮询频率(ms)
- 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() 依赖操作系统的实现,在不同平台上表现会有差异
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
日常在监视文件变化可以选择社区的优秀方案
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', (event, path, details) => { // internal
log('Raw event info:', event, path, details);
});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2013-09-01 据说每个大牛、小牛都应该有自己的库——框架篇