Nodejs文件监听

Nodejs,实现文件监听,可以使用fs.watchfs.watchFile

也可以通过第三方库来实现,本文主要介绍chokidar的使用。

fs.watch

官网例子:

1
2
3
4
5
6
7
8
fs.watch('somedir', (eventType, filename) => {
console.log(`event type is: ${eventType}`);
if (filename) {
console.log(`filename provided: ${filename}`);
} else {
console.log('filename not provided');
}
});

fs.watch的不支持子文件夹的侦听,而且在很多情况下会侦听到两次事件。

chokidar

安装什么的就不介绍了,参考官方文档

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class ContentPackWatcher {
constructor(robot, options = {awaitWriteFinish: true}) {
let dirPath = `${process.env.HUBOT_ENTERPRISE_PACKAGES_DIR}/*.zip`;
this.watcher = Chokidar.watch(dirPath, options);
this.watcher
.on('add', this.addFileListener.bind(this))
.on('addDir', this.addDirectoryListener.bind(this))
.on('change', this.fileChangeListener.bind(this))
.on('unlink', this.fileDeleteListener.bind(this))
.on('unlinkDir', this.directoryDeleteListener.bind(this))
.on('error', this.errorListener.bind(this))
.on('ready', this.readyListener.bind(this));
}
getWatched() {
return this.watcher.getWatched();
}
stopWatch(paths) {
this.watcher.unwatch(paths);
}
readyListener() {
logger.info('Initial scan complete. Ready for changes.');
}
errorListener(error) {
logger.error('Error happened', error)
}
//add new file
addFileListener(filePath, stats) {
if (stats.size > 0) {
logger.info(`File ${filePath} has been added, size: ${stats.size}.`);
}
}
//add new directory
addDirectoryListener(dirPath) {
logger.info(`Directory ${dirPath} has been added.`);
}
//watch file change
fileChangeListener(filePath, stats) {
if (stats.size > 0) {
logger.info(`File ${filePath} has been changed, size: ${stats.size}.`);
}
}
//watch file delete
fileDeleteListener(filePath) {
logger.info(`File ${filePath} has been removed.`);
}
//watch directory delete
directoryDeleteListener(dirPath) {
logger.info(`Directory ${dirPath} has been removed.`);
}
}

API

1
chokidar.watch(paths, [options])
  • paths: 可以是一个字符串数组或一个字符串。
  • options: 对象。
    • persistent: 默认true,进程是否持续监听文件,如果设置为false,当使用fsevents监听时,ready之后不会触发任何监听事件。
    • ignored: 忽略某些文件的监听,
    • ignoreInitial: 默认false,如果设置为false,在初始化chokidar实例时,如果监听到匹配的文件也会被触发add/addDir事件。
    • followSymlinks: 默认true,如果设置为false,只看符号链接本身的变化。
    • cwd: 监听的路径的 base 目录。
    • disableGlobbing: 默认false,如果设置为 true,那么传递给.watch()add()的字符串被视为文字路径名,即使它们看起来就像 globs。
    • usePolling: 默认false,是否使用fs.watchFile (backed by polling), 或者 fs.watch,如果轮询导致CPU占用过高,可以设置为false
      它通常需要设置true当通过网络监听文件时和非标准的情况下。在OS X 上设置为true,会覆盖useFsEvents,也可以设置CHOKIDAR_USEPOLLING环境变量
      来覆盖它。
    • Polling-specific设置(只在usePolling: true是有效)
      • interval:(default: 100).文件系统轮询时间间隔,也可以通过设置环境变量CHOKIDAR_INTERVAL来覆盖它。
      • binaryInterval:(default: 300).二进制文件系统轮询时间间隔。
    • useFsEvents:(default: true on OS X)当fsevents 的监听接口可用时,是否启用。当显式地设置为true,fsevents 取代usePolling
      在OS X 上设置为false时,usePolling: true变为默认。
    • alwaysStat: 默认false,如果add,addDirchange事件依赖fs.Stats对象(callback的第二个参数),设置为true时,可以确保传入这个对象,尽管
      它不是可用的。
    • depth: 默认undefined,遍历子目录的层级。
    • awaitWriteFinish: 默认false,默认情况下,文件第一次出现在磁盘上,文件被写完之前,就会触发add事件。此外,在某些情况下会触发change事件,
      在一些情况下,特别是监听大文件,需要在等待写操作完成以后回复一个文件创建或者修改。设置为true,会检查文件大小,直到文件在设置的时间内(stabilityThreshold)不再改变,才会
      触发add或者change事件。设置适当的时间依赖系统和硬件。awaitWriteFinish可以是一个object,包含下面的属性:
      • stabilityThreshold: (default: 2000)单位毫秒,等待文件大小不再改变的时间,在设置时间之后触发事件。
      • pollInterval: (default: 100),检查文件大小的时间间隔。
    • ignorePermissionErrors: 默认false,忽略没有权限操作文件的error。

事件

chokidar可以通过on方法监听到下面的事件:

  • add, 文件添加
  • addDir, 文件夹添加
  • change, 文件变化
  • unlink, 文件删除
  • unlinkDir, 文件夹删除
  • ready
  • raw
  • error

除了readyrawerror这三个事件,其他事件触发都可以拿到文件路径。

方法

  • .add(path / paths): 添加监听文件。参数可以是一个字符串数组或一个字符串。
  • .on(event, callback): 监听事件,除了readyrawerror这三个事件,其他事件的callback函数的第一个参数是文件路径。
  • .unwatch(path / paths): 停止监听某个文件。参数可以是一个字符串数组或一个字符串。
  • .close(): 删除所有文件监听。
  • .getWatched(): 返回一个包含所有被监听的文件的对象。