Как мне закрыть поток, в котором больше нет данных для отправки в node.js?

Я использую node.js и читаю ввод с последовательного порта, открывая файл /dev/tty, отправляю команду и читаю результат команды и хочу закрыть поток после прочтения и анализа всех данных, Я знаю, что я закончил чтение данных и конец маркера данных. Я обнаружил, что после закрытия потока моя программа не завершается.

Ниже приведен пример того, что я вижу, но использует /dev/random для медленной генерации данных (при условии, что ваша система мало что делает). Я обнаружил, что процесс завершится, как только устройство сгенерирует данные после закрытия потока.

var util = require('util'),
    PassThrough = require('stream').PassThrough,
    fs = require('fs');

// If the system is not doing enough to fill the entropy pool
// /dev/random will not return much data.  Feed the entropy pool with :
//  ssh <host> 'cat /dev/urandom' > /dev/urandom
var readStream = fs.createReadStream('/dev/random');
var pt = new PassThrough();

pt.on('data', function (data) {
    console.log(data)
    console.log('closing');
    readStream.close();  //expect the process to terminate immediately
});

readStream.pipe(pt);

Обновление:1

Я вернулся к этой проблеме и имею другой пример, этот просто использует pty и легко воспроизводится в repl узла. Войдите в систему на 2 терминалах и используйте pty терминала, который вы не используете, в приведенном ниже вызове createReadStream.

var fs = require('fs');
var rs = fs.createReadStream('/dev/pts/1'); // a pty that is allocated in another terminal by my user
//wait just a second, don't copy and paste everything at once
process.exit(0);

в этот момент узел просто зависнет и не выйдет. Это на 10.28.

3 ответа

Вместо того, чтобы использовать

readStream.close(), 

попробуйте использовать

readStream.pause().

Но, если вы используете новейшую версию узла, оберните поток чтения объектом, созданным из потокового модуля с помощью isaacs, например так:

var Readable = require('stream').Readable;
var myReader = new Readable().wrap(readStream);

и используйте myReader вместо readStream после этого.

Удачи! Скажи мне, если это работает.

я на самом деле подключаюсь к http-запросу.. так что для меня это примерно:

      pt.on('close', (chunk) => {
  req.abort();
});

Вы закрываете /dev/random поток, но у вас все еще есть слушатель для 'data' событие сквозной передачи, которое будет поддерживать работу приложения до тех пор, пока сквозная передача не будет закрыта.

Я предполагаю, что есть некоторые буферизованные данные из потока чтения, и пока это не сброшено, проход не закрыт. Но это всего лишь предположение.

Чтобы получить желаемое поведение, вы можете удалить прослушиватель событий при передаче следующим образом:

pt.on('data', function (data) {
  console.log(data)
  console.log('closing');

  pt.removeAllListeners('data');
  readStream.close();
});
Другие вопросы по тегам