Пропущенные события потока для чтения пустого файла внутри таймаута

#node.js

#node.js

Вопрос:

Я работаю над кодом, который считывает из файла и включает код таймаута. У меня возникли некоторые проблемы с пустыми файлами.

Без тайм-аута ниже будет напечатано что-то вроде «readable: true, open, data (0 раз), end». Это работает одинаково с пустым файлом или файлом с содержимым. При таймауте (даже равном 0) поведение сильно меняется в зависимости от того, является ли файл пустым. Для файла с содержимым я получаю что-то вроде того, что я делал без тайм-аута, но с пустым файлом все, что я получаю, это «readable: false».

Почему это работает так по-другому с пустыми файлами, когда у меня есть тайм-аут (даже 0)? Есть ли простое решение этой проблемы?

 var stream = fs.createReadStream(fileNameTarget);
stream.pause();
setTimeout(function() {
  stream.resume()
  console.log('readable: '   stream.readable);
  stream.on('open', function() {
    console.log('open');
  });
  stream.on('data', function() {
    console.log('data');
  });
  stream.on('end', function() {
    console.log('end');
  });
}, 0);
  

Ответ №1:

Разница в том, что setTimeout возвращает управление циклу событий узла.

Это означает, что, хотя without setTimeout control не покидает ваш код до тех пор, пока все обработчики событий потока не будут настроены, в версии с setTimeout может произойти следующее:

  1. Вы начинаете чтение потока в var stream = fs.createReadStream(fileNameTarget);
  2. Управление немедленно передается в цикл событий узла с setTimeout
  3. 'open' , 'data' и 'end' события запущены, но обработчики еще не настроены (поскольку setTimeout обратный вызов еще не занял свою очередь для выполнения).
  4. setTimeout выполняется обратный вызов, но файл уже прочитан.

Файл с содержимым читается и открывается медленнее, следовательно, вы получаете то же поведение, что и без setTimeout — все события потока происходят после события таймаута.

Комментарии:

1. Я добавил паузу и возобновление, которые, как я думал, предотвратят потерю событий. Я все еще получаю аналогичный вывод. Ожидается ли это?

2. @EmilyGerner-Microsoft это странно.

3. @fmsf stream.pause() приостанавливает только выдачу события потока, а не всю среду выполнения

4. @EmilyGerner-Тайна Microsoft раскрыта! stream.pause() только приостанавливает выдачу 'data' событий. Таким образом, 'open' пауза не повлияет. Вы не получаете stream.readable == false в этом случае, не так ли?

5. Я понял, что pause () только приостановил выдачу события — я надеялся предотвратить передачу end! Действительно ли он все еще выдает end даже в состоянии паузы? Чтобы ответить на ваш вопрос, с добавлением паузы я иногда получаю readable: false, в других случаях я получаю stream.readable == true и событие открытия и завершения. Какая-то временная проблема. Идеи?