fs: make unwatchFile() remove a specific listener

Before this commit, `fs.unwatchFile(path)` removed *all* listeners for `path`.

The function is overloaded now: `fs.unwatchFile(path)` still removes all
listeners, but `fs.unwatchFile(path, cb)` lets you remove a specific listener.

Fixes #3660.
This commit is contained in:
Ben Noordhuis 2012-07-08 16:31:07 +02:00
parent bf539f9bfd
commit 5b5362aa8d
3 changed files with 53 additions and 11 deletions

View File

@ -461,12 +461,16 @@ These stat objects are instances of `fs.Stat`.
If you want to be notified when the file was modified, not just accessed
you need to compare `curr.mtime` and `prev.mtime`.
## fs.unwatchFile(filename)
## fs.unwatchFile(filename, [listener])
Stability: 2 - Unstable. Use fs.watch instead, if available.
Stop watching for changes on `filename`.
Stop watching for changes on `filename`. If `listener` is specified, only that
particular listener is removed. Otherwise, *all* listeners are removed and you
have effectively stopped watching `filename`.
Calling `fs.unwatchFile()` with a filename that is not being watched is a
no-op, not an error.
## fs.watch(filename, [options], [listener])

View File

@ -943,10 +943,18 @@ fs.watchFile = function(filename) {
return stat;
};
fs.unwatchFile = function(filename) {
var stat;
if (inStatWatchers(filename)) {
stat = statWatchers[filename];
fs.unwatchFile = function(filename, listener) {
if (!inStatWatchers(filename)) return;
var stat = statWatchers[filename];
if (typeof listener === 'function') {
stat.removeListener('change', listener);
} else {
stat.removeAllListeners('change');
}
if (stat.listeners('change').length === 0) {
stat.stop();
statWatchers[filename] = undefined;
}

View File

@ -26,6 +26,7 @@ var fs = require('fs');
var watchSeenOne = 0;
var watchSeenTwo = 0;
var watchSeenThree = 0;
var startDir = process.cwd();
var testDir = common.fixturesDir;
@ -37,12 +38,16 @@ var filenameTwo = 'hasOwnProperty';
var filepathTwo = filenameTwo;
var filepathTwoAbs = path.join(testDir, filenameTwo);
var filenameThree = 'charm'; // because the third time is
process.on('exit', function() {
fs.unlinkSync(filepathOne);
fs.unlinkSync(filepathTwoAbs);
fs.unlinkSync(filenameThree);
assert.equal(1, watchSeenOne);
assert.equal(1, watchSeenTwo);
assert.equal(2, watchSeenTwo);
assert.equal(1, watchSeenThree);
});
@ -86,13 +91,38 @@ assert.throws(
assert.doesNotThrow(
function() {
fs.watchFile(filepathTwo, function(curr, prev) {
fs.unwatchFile(filepathTwo);
function a(curr, prev) {
fs.unwatchFile(filepathTwo, a);
++watchSeenTwo;
});
}
function b(curr, prev) {
fs.unwatchFile(filepathTwo, b);
++watchSeenTwo;
}
fs.watchFile(filepathTwo, a);
fs.watchFile(filepathTwo, b);
}
);
setTimeout(function() {
fs.writeFileSync(filepathTwoAbs, 'pardner');
}, 1000);
assert.doesNotThrow(
function() {
function a(curr, prev) {
assert.ok(0); // should not run
}
function b(curr, prev) {
fs.unwatchFile(filenameThree, b);
++watchSeenThree;
}
fs.watchFile(filenameThree, a);
fs.watchFile(filenameThree, b);
fs.unwatchFile(filenameThree, a);
}
);
setTimeout(function() {
fs.writeFileSync(filenameThree, 'pardner');
}, 1000);