fs.watch( 'example.xml', function ( curr, prev ) {
// on file change we can read the new xml
fs.readFile( 'example.xml','utf8', function ( err, data ) {
if ( err ) throw err;
console.dir(data);
console.log('Done');
});
});
SORTIE:
- quelques données
- Fait X 1
- quelques données
- Fait X 2
C'est ma faute d'utilisation ou ..?
L'API fs.watch
:
Je tiens compte de cela en procédant comme suit:
var fsTimeout
fs.watch('file.js', function(e) {
if (!fsTimeout) {
console.log('file.js %s event', e)
fsTimeout = setTimeout(function() { fsTimeout=null }, 5000) // give 5 seconds for multiple events
}
}
Je suggère de travailler avec chokidar
( https://github.com/paulmillr/chokidar ) qui est beaucoup mieux que fs.watch
:
Commentant son fichier README.md:
Node.js fs.watch
:
rename
.Node.js fs.watchFile
:
Si vous devez surveiller votre fichier pour les modifications, vous pouvez consulter ma petite bibliothèque on-file-change . Il vérifie le hachage du fichier sha1 entre les événements change
déclenchés.
Explication de la raison pour laquelle nous avons plusieurs événements déclenchés:
Vous remarquerez peut-être que dans certaines situations, un seul événement de création génère plusieurs événements créés gérés par votre composant. Par exemple, si vous utilisez un composant FileSystemWatcher pour surveiller la création de nouveaux fichiers dans un répertoire, puis que vous le testez à l'aide du Bloc-notes pour créer un fichier, deux événements créés peuvent être générés même si un seul fichier a été créé. En effet, le Bloc-notes effectue plusieurs actions sur le système de fichiers pendant le processus d’écriture. Le Bloc-notes écrit sur le disque par lots qui créent le contenu du fichier, puis les attributs de fichier. D'autres applications peuvent fonctionner de la même manière. Étant donné que FileSystemWatcher surveille les activités du système d'exploitation, tous les événements déclenchés par ces applications seront récupérés.
Je traite de cette question pour la première fois, donc toutes les réponses à ce jour sont probablement meilleures que ma solution. Cependant, aucune d’entre elles ne convenait parfaitement à mon cas. J’ai donc proposé quelque chose de légèrement différent - j’ai utilisé XOR opération permettant d'inverser un entier compris entre 0 et 1, en gardant effectivement une trace et en ignorant chaque deuxième événement du fichier:
var targetFile = "./watchThis.txt";
var flippyBit = 0;
fs.watch(targetFile, {persistent: true}, function(event, filename) {
if (event == 'change'){
if (!flippyBit) {
var data = fs.readFile(targetFile, "utf8", function(error, data) {
gotUpdate(data);
})
} else {
console.log("Doing nothing thanks to flippybit.");
}
flipBit(); // call flipBit() function
}
});
// Whatever we want to do when we see a change
function gotUpdate(data) {
console.log("Got some fresh data:");
console.log(data);
}
// Toggling this gives us the "every second update" functionality
function flipBit() {
flippyBit = flippyBit ^ 1;
}
Je ne voulais pas utiliser une fonction temporelle (telle que la réponse de jwymanm), car le fichier que je suis en train de regarder pourrait hypothétiquement obtenir des mises à jour légitimes très fréquemment. Et je ne voulais pas utiliser une liste de fichiers surveillés comme le suggère Erik P, car je ne regarde qu'un fichier. La solution de Jan Święcki semblait exagérée, car je travaille sur des fichiers extrêmement courts et simples dans un environnement à faible consommation d'énergie. Enfin, la réponse de Bernado me rendait un peu nerveuse - elle ne pourrait ignorer la deuxième mise à jour que si elle arrivait avant la fin du traitement de la première, et je ne peux pas gérer ce type d'incertitude. Si quelqu'un se retrouvait dans ce scénario très spécifique, l'approche que j'avais utilisée aurait peut-être un sens. Si quelque chose ne va pas, veuillez me le faire savoir/éditer cette réponse, mais jusqu'à présent, elle semble bien fonctionner?
NOTE: Évidemment, ceci fortement suppose que vous obtiendrez exactement 2 événements par changement réel. J'ai soigneusement testé cette hypothèse, évidemment, et appris ses limites. Jusqu'à présent, j'ai confirmé que:
touch
triggers 2 mises à jour >
(écrasement du contenu du fichier) déclenche 2 mises à jour >>
déclenche parfois 1 mise à jour!*Je peux penser parfaitement aux bonnes raisons pour les différents comportements mais nous n'avons pas besoin de savoir pourquoi il se passe quelque chose pour planifier cela - je voulais juste souligner que vous voudrez vérifier par vous-même. propre environnement et dans le contexte de vos propres cas d'utilisation (duh) et ne pas faire confiance à un imbécile auto-avoué sur Internet. Cela étant dit, avec les précautions prises, je n’ai encore eu aucune bizarrerie.
* Divulgation complète, je ne sais pas vraiment pourquoi cela se produit, mais nous avons déjà un comportement imprévisible avec la fonction watch (), alors qu’est-ce qu’un peu plus d’incertitude? Pour ceux qui suivent chez eux, les ajouts plus rapides à un fichier semblent en empêcher la double mise à jour, mais honnêtement, je ne le sais pas vraiment, et je suis à l'aise avec le comportement de cette solution dans le cas réel. être utilisé, qui est un fichier d’une ligne qui sera mis à jour (le contenu sera remplacé) au moins deux fois par seconde.
le premier est le changement et le second est renommé
nous pouvons faire une différence avec la fonction auditeur
function(event, filename) {
}
Le rappel de l'auditeur obtient deux arguments (event, filename). event est 'rename' ou 'change', et filename est le nom du fichier qui a déclenché l'événement.
// rm sourcefile targetfile
fs.watch( sourcefile_dir , function(event, targetfile)){
console.log( targetfile, 'is', event)
}
comme un fichier source est renommé en fichier cible, il appellera trois événements comme un fait
null is rename // sourcefile not exist again
targetfile is rename
targetfile is change
remarquez que si vous voulez attraper tous ces trois evnet, regardez le répertoire de sourcefile
J'obtiens parfois des enregistrements multiples de l'événement Watch, ce qui provoque le déclenchement de l'événement Watch à plusieurs reprises ... Je l'ai résolu en conservant une liste des fichiers en cours de surveillance et en évitant d'enregistrer l'événement si le fichier était déjà dans la liste:
var watchfiles = {};
function initwatch(fn, callback) {
if watchlist[fn] {
watchlist[fn] = true;
fs.watch(fn).on('change', callback);
}
}
......
La solution la plus simple:
const watch = (path, opt, fn) => {
var lock = false
fs.watch(path, opt, function () {
if (!lock) {
lock = true
fn()
setTimeout(() => lock = false, 1000)
}
})
}
watch('/path', { interval: 500 }, function () {
// ...
})
Comme d'autres réponses le dit ... Cela a eu beaucoup de problèmes, mais je peux gérer cela de cette façon:
var folder = "/folder/path/";
var active = true; // flag control
fs.watch(folder, function (event, filename) {
if(event === 'rename' && active) { //you can remove this "check" event
active = false;
// ... its just an example
for (var i = 0; i < 100; i++) {
console.log(i);
}
// ... other stuffs and delete the file
if(!active){
try {
fs.unlinkSync(folder + filename);
} catch(err) {
console.log(err);
}
active = true
}
}
});
J'espère pouvoir vous aider ...
Similaire/même problème. Je devais faire des choses avec des images quand elles ont été ajoutées à un répertoire. Voici comment j'ai traité le double tir:
var fs = require('fs');
var working = false;
fs.watch('directory', function (event, filename) {
if (filename && event == 'change' && active == false) {
active = true;
//do stuff to the new file added
active = false;
});
Il ignorera le deuxième tir jusqu'à ce que termine le nouveau fichier.
Personnellement, j’aime bien utiliser return
pour empêcher l’exécution d’un bloc de code lors de la vérification de quelque chose. Voici donc ma méthode:
var watching = false;
fs.watch('./file.txt', () => {
if(!watching) return;
watching = true;
// do something
// the timeout is to prevent the script to run twice with short functions
// the delay can be longer to disable the function for a set time
setTimeout(() => {
watching = false;
}, 100);
};
N'hésitez pas à utiliser cet exemple pour simplifier votre code. PAS _ peut être préférable à l'utilisation d'un module fourni par d'autres, mais cela fonctionne plutôt bien!