监视文件系统意味着监视特定目录或文件的更改。

有时您可能需要持续观察特定文件或目录的更改。出于这个原因,我们使用像 chokidar 这样的文件系统 Watcher 或内置的 NodeJs 文件系统方法 fs.watch()。
但是我们不会使用上面的方法,让我来告诉你这样做的原因。
fs.watch()
fs 提供了一个应用程序接口 (API),可连续监视文件的更改。可以使用此方法跟踪文件更改,该方法返回一个 fs.FSWatcher 对象。在这里阅读更多关于它的信息 fs.watch()。
缺点:
- 这种方法不可靠,每次修改都可能在监听器中显示多个事件。
- 将大多数更改作为重命名发出。
- 不提供递归查看文件树的简单方法。
- 不报告 OS 上的文件名。
还有很多…
chokidar
它是最流行的文件系统观察器,但尽管在某些情况下它可能就足够了,但它并不完美。
优点:
- 它支持处理符号链接。
- 它有一些内置支持,可以在执行原子写入时处理写入磁盘的临时文件,尽管在 Watcher 中忽略它们也很简单,您可以通过忽略选项忽略它们。
- 它可以更可靠地观察网络连接的路径,尽管在观察大量文件时会导致性能问题。
- 尽管 Watcher(一个文件系统观察程序库,我们稍后会讨论)具有更全面的测试套件并且也用于生产(例如在 Notable 中,它之前使用了 chokidar),但它经过了更多的实战测试。
缺点:
- 它需要原生依赖才能在 macOS 下进行高效的递归观察,而原生依赖可能很难使用。
- 在 下它不能有效地递归地观察,另一方面,Watcher(一个文件系统观察器库,我们将在后面讨论)是建立在 Node 的 Windows 原生递归观察能力之上的。
- 它无法检测重命名。
- 如果您不需要像 globbing 这样的功能,那么 chokidar 会不必要地膨胀您的应用程序包。
- EMFILE 错误没有得到正确处理,因此如果您观看的文件足够多,chokidar 最终会放弃它们。
因为每种方法都有自己的缺点。现在让我们来看看解决方案。
Watcher
一个追求完美的文件系统观察者,没有原生依赖和可选的重命名检测支持。
我自己使用过这个库,与其他替代方案相比,我发现它非常简单且无错误。
特征:
- 可靠:该库旨在处理处理文件系统时可能出现的所有问题,包括一些最流行的无法处理的替代方案,例如 EMFILE 错误。
- 重命名检测:这个库可以选择性地检测文件和目录何时被重命名,这允许您在某些情况下为您的用户提供更好的体验。
- 性能:在可用时使用本机递归监视(macOS 和 Windows),否则可以有效地手动执行。
- 没有原生依赖:原生依赖使用起来会很痛苦,这个库使用了其中的 0 个。
- 不臃肿:许多替代观察者附带可能无用且昂贵的功能,例如对通配的支持,这个库旨在更精简,同时仍然公开正确的抽象,让您可以根据需要使用通配。
- TypeScript-ready:这个库是用 TypeScript 编写的,所以类型不是事后才想到的,而是随库一起提供的。
您可以在此处查看与其他观察者的比较。
安装:
npm install — save watcher
用法:
你会像这样使用这个库:
const Wattcher = require('watcher')
// Watching a single path
const watcher = new Watcher ( '/foo/bar' );
// Watching multiple paths
const watcher = new Watcher ( ['/foo/bar', '/baz/qux'] );
// Passing some options
const watcher = new Watcher ( '/foo/bar', { renameDetection: true } );
// Passing an "all" handler directly
const watcher = new Watcher ( '/foo/bar', {}, ( event, targetPath, targetPathNext ) => {} );
// Attaching the "all" handler manually
const watcher = new Watcher ( '/foo/bar' );
watcher.on ( 'all', ( event, targetPath, targetPathNext ) => { // This is what the library does internally when you pass it a handler directly
console.log ( event ); // => could be any target event: 'add', 'addDir', 'change', 'rename', 'renameDir', 'unlink' or 'unlinkDir'
console.log ( targetPath ); // => the file system path where the event took place, this is always provided
console.log ( targetPathNext ); // => the file system path "targetPath" got renamed to, this is only provided on 'rename'/'renameDir' events
});
// Listening to individual events manually
const watcher = new Watcher ( '/foo/bar' );
watcher.on ( 'error', error => {
console.log ( error instanceof Error ); // => true, "Error" instances are always provided on "error"
});
watcher.on ( 'ready', () => {
// The just finished instantiation and may soon emit some events
});
watcher.on ( 'close', () => {
// The app just stopped watching and will not emit any further events
});
watcher.on ( 'all', ( event, targetPath, targetPathNext ) => {
console.log ( event ); // => could be any target event: 'add', 'addDir', 'change', 'rename', 'renameDir', 'unlink' or 'unlinkDir'
console.log ( targetPath ); // => the file system path where the event took place, this is always provided
console.log ( targetPathNext ); // => the file system path "targetPath" got renamed to, this is only provided on 'rename'/'renameDir' events
});
watcher.on ( 'add', filePath => {
console.log ( filePath ); // "filePath" just got created, or discovered by the watcher if this is an initial event
});
watcher.on ( 'addDir', directoryPath => {
console.log ( filePath ); // "directoryPath" just got created, or discovered by the watcher if this is an initial event
});
watcher.on ( 'change', filePath => {
console.log ( filePath ); // "filePath" just got modified
});
watcher.on ( 'rename', ( filePath, filePathNext ) => {
console.log ( filePath, filePathNext ); // "filePath" got renamed to "filePathNext"
});
watcher.on ( 'renameDir', ( directoryPath, directoryPathNext ) => {
console.log ( directoryPath, directoryPathNext ); // "directoryPath" got renamed to "directoryPathNext"
});
watcher.on ( 'unlink', filePath => {
console.log ( filePath ); // "filePath" got deleted, or at least moved outside the watched tree
});
watcher.on ( 'unlinkDir', directoryPath => {
console.log ( directoryPath ); // "directoryPath" got deleted, or at least moved outside the watched tree
});
// Closing the watcher once you are done with it
watcher.close ();
// Updating watched roots by closing a watcher and opening an updated one
watcher.close ();
watcher = new Watcher ( /* Updated options... */ );
关注七爪网,获取更多APP//源码资源!
胜象大百科









