3

Решил написать свой livereload и сразу же "уперся" в проблему: на одно изменение файла генерируется 2-3 одинаковых события (или я что-то не так понимаю).

Скрипт взят из документации: watchFs.js

const fs  = require("fs"); 

fs.watch(__dirname,{recursive:true},(eventType, filename)=>{
    console.log(`Тип события: ${eventType}`);
  if (filename) {
    console.log(`Имя файла: ${filename}`);
  } else {
    console.log('Имя файла отсутствует');
  } 
})  

Структура папок:

введите сюда описание изображения

Вывод консоли. Полоса делит вывод консоли на 2 изменения: одно было сделано в корневой папке, другое в подкаталоге

введите сюда описание изображения

Как это побороть?

Dmytro
  • 6,756
  • У меня под linux-ом всё работает как ожидается. На странице документации к модулю File System секцию Caveats посмотрите. Походу проблема от винды. Мало вероятно, но может еще ваш редактор "хочет помочь" и сохраняет файл при изменении или по интервалу времени. – alvoro Jun 18 '18 at 18:33
  • @alvoro, нашел вот такой ответ разработчиков на подобный вопрос:"This is expected. The file is first truncated when it is opened, and then data is written. This triggers 2 change events. We cannot and won't do anything to prevent that." https://github.com/nodejs/node-v0.x-archive/issues/2126#issuecomment-6633415 . - "Мы не можем и не хотим ничего делать с этим". Печалька( – Dmytro Jun 19 '18 at 06:51
  • Вот выход - игнорить первое событие. Но лучше явно написать if(isWinda){ ... } – alvoro Jun 19 '18 at 08:18
  • 1
    В моём питончике некоторые библиотеки для отслеживания изменений сперва коллекционируют все события одного файла в течение какого-то времени (в watchdog по умолчанию полсекунды, например) и потом выдают слушателям одно единое событие изменения для файла. Возможно, здесь в js тоже стоит делать что-то подобное (или найти библиотеку, которая это делает за вас) – andreymal Jun 20 '18 at 06:07
  • @andreymal, хорошая идея – Dmytro Jun 20 '18 at 06:29

1 Answers1

1

Нашел такой выход из положения:

const fs  = require("fs"); 

function watchFs(pathWatch){
    const watcher = fs.watch(pathWatch,{recursive:true},(eventType, filename)=>{
        watcher.close();
         console.log(`Тип события: ${eventType}`);
      if (filename) {
        console.log(`Имя файла: ${filename}`);
      } else {
        console.log('Имя файла отсутствует');
      } 

      setTimeout(function(){
        watchFs(pathWatch)
      },10)
    });
}
Dmytro
  • 6,756
  • А не будет ли пропущено какое-то другое событие, пока setTimeout не сработал? – andreymal Jun 20 '18 at 06:04
  • @andreymal, хорошее замечание...для других целей, это, скорее всего, действительно надо будет проверять. А при реализации livereload, я думаю, что не стоит об этом беспокоиться. – Dmytro Jun 20 '18 at 06:31