Ubuntu 12.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"
要点上的整个代码:https://gist.github.com/2621576
每次我保存一个被监视的文件时,主函数被调用两次而不是一次。 我的编辑是Sublime Text 2。
输出字可以看出:
fs.watchFile不稳定。从节点文档:
fs.watchFile(filename,[options],listener)#
稳定性:2 - 不稳定。如果可用,请改用fs.watch。
你可以尝试fs.watch
,但不幸的是它可能会遇到同样的问题。当我试图创建一个类似的fs.watch
时,我在Windows上与monitor script有同样的问题。
解决方法是记录修改发生的时间,如果在几毫秒内触发,则忽略第二个更改。有点难看,但它的确有效。
现在已经解决了问题(至少)与fs.watch
。我没有尝试fs.watchFile
,因为它不是NodeJS文档推荐的。
change
事件rename
事件,一个用于当前名称,另一个用于新名称rename
事件。我的环境:macOS 10.12.6和NodeJS v11.10.1
问题仍然存在,这是我找到的方式。
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
});
我们检查上次修改时间是否有所不同,然后继续。
我建议尝试node-inotify-plusplus(https://github.com/coolaj86/node-inotify-plusplus),它比fs.watchFile或fs.watch更适合我。
如果你使用下划线或lodash,你可以考虑使用油门并丢弃后缘上的调用。一个基本的例子是
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();
为了解决这个问题,我跟踪以前的“文件修改”时间戳,如果值相同,则不运行我的正常回调代码。
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
});
});
我通过每次收到更新时将'ignore'标志从false翻转为true来解决这个问题,从而忽略每一个第二个事件。但我还发现,有时,对文件的更改只会导致一次更新。我不确定是什么导致了这种情况,但是当更新非常频繁,并且当这些更新被追加时(>>
),它似乎发生了。我没有观察到任何触发两个以上事件的单个更改的实例。
在this question中有关于这个问题的更多讨论。我还为我的解决方案发布了一些示例代码。
另一个建议是npm模块比fs.watch
或fs.watchFile
好得多:
与debouncing
相似:
let fsWait = false;
fs.watch("file.txt", (event, filename) => {
if(fsWait)return;
fsWait = setTimeout(() => fsWait = false, 1000);
/* own code here */
});
它与原始问题没有直接关系,但你知道这句话是什么意思吗? (来自fs.watch
documentation)。
另请注意,侦听器回调附加到fs.FSWatcher触发的“change”事件,但它与eventType的“change”值不同。