七爪源码:使用 NodeJs 观看文件系统

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

有时您可能需要持续观察特定文件或目录的更改。出于这个原因,我们使用像 chokidar 这样的文件系统 Watcher 或内置的 NodeJs 文件系统方法 fs.watch()。

但是我们不会使用上面的方法,让我来告诉你这样做的原因。


fs.watch()

fs 提供了一个应用程序编程接口 (API),可连续监视文件的更改。可以使用此方法跟踪文件更改,该方法返回一个 fs.FSWatcher 对象。在这里阅读更多关于它的信息 fs.watch()。

缺点:

  • 这种方法不可靠,每次修改都可能在监听器中显示多个事件。
  • 将大多数更改作为重命名发出。
  • 不提供递归查看文件树的简单方法。
  • 不报告 MacOS 上的文件名。

还有很多…


chokidar

它是最流行的文件系统观察器,但尽管在某些情况下它可能就足够了,但它并不完美。

优点:

  • 它支持处理符号链接。
  • 它有一些内置支持,可以在执行原子写入时处理写入磁盘的临时文件,尽管在 Watcher 中忽略它们也很简单,您可以通过忽略选项忽略它们。
  • 它可以更可靠地观察网络连接的路径,尽管在观察大量文件时会导致性能问题。
  • 尽管 Watcher(一个文件系统观察程序库,我们稍后会讨论)具有更全面的测试套件并且也用于生产(例如在 Notable 中,它之前使用了 chokidar),但它经过了更多的实战测试。

缺点:

  • 它需要原生依赖才能在 macOS 下进行高效的递归观察,而原生依赖可能很难使用。
  • 在 Windows 下它不能有效地递归地观察,另一方面,Watcher(一个文件系统观察器库,我们将在后面讨论)是建立在 Node 的 Windows 原生递归观察能力之上的。
  • 它无法检测重命名。
  • 如果您不需要像 globbing 这样的功能,那么 chokidar 会不必要地膨胀您的应用程序包。
  • EMFILE 错误没有得到正确处理,因此如果您观看的文件足够多,chokidar 最终会放弃它们。

因为每种方法都有自己的缺点。现在让我们来看看解决方案。


Watcher

一个追求完美的文件系统观察者,没有原生依赖和可选的重命名检测支持。

我自己使用过这个库,与其他替代方案相比,我发现它非常简单且无错误。

特征:

  1. 可靠:该库旨在处理处理文件系统时可能出现的所有问题,包括一些最流行的无法处理的替代方案,例如 EMFILE 错误。
  2. 重命名检测:这个库可以选择性地检测文件和目录何时被重命名,这允许您在某些情况下为您的用户提供更好的体验。
  3. 性能:在可用时使用本机递归监视(macOS 和 Windows),否则可以有效地手动执行。
  4. 没有原生依赖:原生依赖使用起来会很痛苦,这个库使用了其中的 0 个。
  5. 不臃肿:许多替代观察者附带可能无用且昂贵的功能,例如对通配的支持,这个库旨在更精简,同时仍然公开正确的抽象,让您可以根据需要使用通配。
  6. 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 app 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/小程序/网站源码资源!

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章