Node.js 为什么fs.watchFile在节点中调用了两次?
Node.js 为什么fs.watchFile在节点中调用了两次?,node.js,Node.js,ubuntu12.04Node v0.6.14CoffeeScript 1.3.1 fs.watchFile coffee_eval, (e) -> console.log e result = spawn 'coffee', ['-bc', coffee_eval] msg = '' result.stderr.on 'data', (str) -> msg+= str result.stderr.on 'end', -> console.
ubuntu12.04
Node v0.6.14
CoffeeScript 1.3.1
fs.watchFile coffee_eval, (e) ->
console.log e
result = spawn 'coffee', ['-bc', coffee_eval]
msg = ''
result.stderr.on 'data', (str) ->
msg+= str
result.stderr.on 'end', ->
console.log 'msg: ', msg
print "!! #{coffee_eval}\n"
关于要点的完整代码:
每次我保存一个被监视的文件时,主函数被称为twitce,而不是一次。我的编辑是Sumline Text 2 输出字可参见:
fs.watchFile不稳定。从节点文档: fs.watchFile(文件名,[options],侦听器)# 稳定性:2-不稳定。如果可用,请改用fs.watch 您可以尝试
fs.watch
,但不幸的是,它可能会遇到同样的问题。在windows上尝试创建类似的应用程序时,我遇到了与fs.watch相同的问题
解决方法是记录修改发生的时间,如果在几毫秒内触发,则忽略第二次更改。有点难看,但它确实有效。我建议尝试node inotify plusplus(),它比fs.watchFile或fs.watch更适合我。为了解决这个问题,我会跟踪以前的“file modified”时间戳,如果值相同,就不运行正常的回调代码
var filename = "/path/to/file";
var previousMTime = new Date(0);
var watcher = fs.watch(filename, {
persistent: false
}, function(){
fs.stat(filename, function(err, stats){
if(stats.mtime.valueOf() === previousMTime.valueOf()){
console.log("File Update Callback Stopped (same revision time)");
return;
}
previousMTime = stats.mtime;
// do your interesting stuff down here
});
});
如果你使用下划线或LADASH,你可以考虑使用节流阀并丢弃后缘上的呼叫。一个基本的例子是
var fs = require('fs');
var _ = require("lodash");
function FileWatcher (fileName)
{
this.file = fileName;
this.onChange = _.throttle(this.trigger, 100, {leading: false});
}
FileWatcher.prototype.observe = function ()
{
fs.watch(this.file, this.onChange);
}
FileWatcher.prototype.trigger = function ()
{
console.log("file changed :)");
}
var fileToWatch = __dirname + "/package.json";
new FileWatcher(fileToWatch).observe();
我解决了这个问题,每次收到更新时都将“忽略”标志从false翻转为true,从而忽略每一秒的事件但是我还发现,有时候,对文件的更改只会导致一次更新。我不确定是什么原因导致了这种情况,但它似乎发生在更新非常频繁的时候,以及那些更新是附加的时候(
>
)。我没有观察到任何单一变化触发两个以上事件的情况
关于这个问题的讨论更多。我还在那里发布了我的解决方案的一些示例代码。关于npm模块的另一个建议,它比
fs.watch
或fs.watchFile
好得多:
问题仍然存在,以下是我找到的方法
var actionDone = {}
fs.watch('.', function(x,filename) {
var path = './'+filename;
var stats = fs.statSync(path);
let seconds = +stats.mtime;
if(actionDone[filename] == seconds) return;
actionDone[filename] = seconds
//write your code here
});
我们检查上次修改的时间是否不同,然后继续。这与原始问题没有直接关系,但你知道这句话的意思吗?(从
fs.watch
)
还要注意,侦听器回调附加到fs.FSWatcher触发的“change”事件,但它与eventType的“change”值不同
该问题已通过
fs(至少)修复。请立即观看。我没有尝试fs.watchFile
,因为NodeJS文档不推荐它
- 每次修改文件时都会发生一个
change
事件
- 2
重命名
更改文件名时发生的事件,一个用于当前名称,一个用于新名称
- 新创建的文件(从其他位置复制)或已删除的文件的一个
重命名
事件
我的环境:macOS 10.12.6和NodeJS v11.10.1截至2017年1月,fs.watch
和fs.watchFile
或多或少都比较稳定(文档没有明确提到它们的稳定性问题),但不同平台之间确实存在细微的差异。这些问题在2019年仍然存在。我在Windows上使用fs.watch时也遇到了同样的问题。有趣的是,使用fs.watchFile(他们在文档中建议不要使用)效果很好。但是,当您实际更改文件内容时,仍会触发两个事件:文件在打开时首先被截断,然后写入数据。请看这里:imo这是避免重复触发器的最可靠的方法