当前位置: 首页 > 工具软件 > iNotify.js > 使用案例 >

Node.js 基础篇(九):fs.watchFile

常英毅
2023-12-01

fs.watch 监视 filename 的变化

fs.watch(filename[, options][, listener])

  • filename <string> | <Buffer> | <URL>
  • options <string> | <Object>
    • persistent <boolean> 指示只要正在监视文件,进程是否应继续运行。 默认值: true
    • recursive <boolean> 指示是应监视所有子目录,还是仅监视当前目录。 这在指定目录时适用,并且仅在受支持的平台上有效(请参见注意事项)。 默认值: false
    • encoding <string> 指定用于传给监听器的文件名的字符编码。 默认值: 'utf8'
    • signal <AbortSignal> 允许使用中止信号关闭监视器。
  • listener <Function> | <undefined> 默认值: undefined
    • eventType <string>
    • filename <string> | <Buffer>
  • 返回: <fs.FSWatcher>

监视 filename 的变化,其中 filename 是文件或目录。

第二个参数是可选的。 如果 options 作为字符串提供,则它指定 encoding。 否则 options 应作为对象传入。

监听器回调有两个参数 (eventType, filename)eventType'rename''change'filename 是触发事件的文件的名称。

在大多数平台上,只要目录中文件名出现或消失,就会触发 'rename'

监听器回调绑定到由 <fs.FSWatcher> 触发的 'change' 事件,但它与 eventType'change' 值不同。

如果传入了 signal,则中止相应的 AbortController 将关闭返回的 <fs.FSWatcher>。


注意事项#

fs.watch API 跨平台并非 100% 一致,并且在某些情况下不可用。

递归选项仅在 macOS 和 Windows 上受支持。 当在不支持它的平台上使用该选项时,将抛出 ERR_FEATURE_UNAVAILABLE_ON_PLATFORM 异常。

在 Windows 上,如果监视目录被移动或重命名,则不会触发任何事件。 删除监视目录时报 EPERM 错误。


可用性#

此功能取决于底层操作系统提供了一种通知文件系统更改的方法。

  • 在 Linux 系统上,这使用 inotify(7)
  • 在 BSD 系统上,这使用 kqueue(2)
  • 在 macOS 上,这对文件使用 kqueue(2),对目录使用 FSEvents
  • 在 SunOS 系统(包括 Solaris 和 SmartOS)上,这使用 event ports
  • 在 Windows 系统上,此功能取决于 ReadDirectoryChangesW
  • 在 AIX 系统上,此功能依赖于必须启用的 AHAFS
  • 在 IBM i 系统上,不支持此功能。

如果底层功能由于某种原因不可用,则 fs.watch() 将无法运行并可能抛出异常。 例如,使用虚拟化软件(例如 Vagrant 或 Docker)时,在网络文件系统(NFS、SMB等)或主机文件系统上监视文件或目录可能不可靠,在某些情况下甚至是不可能的。

仍然可以使用 fs.watchFile(),它使用 stat 轮询,但这种方法较慢且不太可靠。


索引节点#

在 Linux 和 macOS 系统上,fs.watch() 解析索引节点的路径并监视索引节点。 如果监视路径被删除并重新创建,则会为其分配一个新的索引节点。 监视将触发删除事件,但将继续监视原始索引节点。 不会发出新索引节点的事件。 这是预期的行为。

AIX 文件在文件的生命周期内保留相同的索引节点。 在 AIX 上保存和关闭监视文件将产生两个通知(一个用于添加新内容,另一个用于截断)。


**文件名参数**[#](http://nodejs.cn/api/fs.html#filename-argument)

仅在 Linux、macOS、Windows 和 AIX 上支持在回调中提供 filename 参数。 即使在支持的平台上,也不能保证始终提供 filename。 因此,不要假设回调中总是提供 filename 参数,如果它为 null,则有一些回退逻辑。

import { watch } from '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.watchFile 监视 filename 的变化

fs.watchFile(filename[, options], listener)#

  • filename <string> | <Buffer> | <URL>
  • options <Object>
    • bigint <boolean> 默认值: false
    • persistent <boolean> 默认值: true
    • interval <integer> 默认值: 5007
  • listener <Function>
  • 返回: <fs.StatWatcher>

监视 filename 的变化。 每次访问文件时都会调用回调 listener

可以省略 options 参数。 如果提供,它应该是一个对象。 options 对象可以包含名为 persistent 的布尔值,其指示当文件正在被监视时,进程是否应该继续运行。 options 对象可以指定 interval 属性,指示应该轮询目标的频率(以毫秒为单位)。

listener 具有两个参数,当前的统计对象和上一个统计对象:

import { watchFile } from 'fs';

watchFile('message.text', (curr, prev) => {
  console.log(`the current mtime is: ${curr.mtime}`);
  console.log(`the previous mtime was: ${prev.mtime}`);
});

这些统计对象是 fs.Stat 的实例。 如果 bigint 选项为 true,则这些对象中的数值被指定为 BigInt

要在文件被修改(而不仅仅是访问)时得到通知,则需要比较 curr.mtimeMsprev.mtimeMs

fs.watchFile 操作导致 ENOENT 错误时,它将调用监听器一次,且所有字段均清零(或者,对于日期,则为 Unix Epoch)。 如果文件是后来创建的,则将使用最新的统计对象再次调用监听器。 这是自 v0.10 以来的功能变化。

使用 fs.watch()fs.watchFilefs.unwatchFile 更高效。 应尽可能使用 fs.watch 而不是 fs.watchFilefs.unwatchFile

fs.watchFile() 正在监视的文件消失并重新出现时,则第二个回调事件(文件的重新出现)中的 previous 的内容将与第一个回调事件(文件的消失)中的 previous 的内容相同。

这发生在:

  • 文件被删除,然后恢复
  • 文件被重命名,然后再次重命名回其原始名称
 类似资料: