Node.js записываемый поток: запись против _write - PullRequest
0 голосов
/ 24 апреля 2020

Я читаю официальные Node.js документы для понимания потоков. Я реализую записываемый поток, но я не могу понять, в чем разница между write и _write.

Цитирование документов из этого раздела:

Все вызовы writable.write (), которые происходят между временем вызова writeable._write () и обратным вызовом, приведут к буферизации записанных данных. Когда вызывается обратный вызов, поток может генерировать событие «утечки». Если потоковая реализация способна обрабатывать несколько порций данных одновременно, должен быть реализован метод writable._writev ().

это только дает мне идею, что оба ведут себя по-разному, но я могу ' не могу понять, как это сделать.

Может быть, взяв пример, основанный на здесь в документации, кто-нибудь может объяснить, в чем заключается разница в поведении приведенных ниже фрагментов кода при получении данных от Readable/Transform поток? Что такое аналоги write и _write в потоке Readable, если есть?

const { Writable } = require('stream');

const myWritable = new Writable({
  write(chunk, encoding, callback) {
    if (chunk.toString().indexOf('a') >= 0) {
      callback(new Error('chunk is invalid'));
    } else {
      callback();
    }
  }
});
const { Writable } = require('stream');

class MyWritable extends Writable {
  _write(chunk, encoding, callback) {
    if (chunk.toString().indexOf('a') >= 0) {
      callback(new Error('chunk is invalid'));
    } else {
      callback();
    }
  }
}

1 Ответ

1 голос
/ 24 апреля 2020

В ваших конкретных c двух примерах, я думаю, что первый пример неправильный, или они пытаются проиллюстрировать некоторые (непрактичные) и академические c пункты. Это должно быть переопределение _write(), а не write(). Если вы переопределяете write(), то вы на самом деле не используете какую-либо внутреннюю потоковую логику c или вам нужно немного изменить то, что входит, а затем вызвать базовую реализацию write(). В этом примере вы просто берете интерфейс верхнего уровня write() и заменяете его, и, таким образом, вообще не используете никаких внутренних элементов потока.


.write() - это то, что потребитель или пользователь записываемого потока вызывает запись данных в объект потока. Это интерфейс publi c, который, как ожидается, будет использоваться любым пользователем, использующим записываемый поток.

._write() является внутренним интерфейсом. Он НЕ должен вызываться потребителем или пользователем записываемого потока. Он предоставляется разработчиком объекта потока типа c и вызывается самим потоком всякий раз, когда необходимо записать данные в любое хранилище, которое фактически находится за этим потоком. Это часть потоковой абстракции для основного хранилища. Например, если вы реализовали объект потока, представляющий запись в последовательный порт, в качестве реализации этого объекта потока, вам придется переопределить обобщенный c _write() и предоставить реализацию ._write(), которая физически отправляет байты к последовательному порту всякий раз, когда случается так, что инфраструктура потока вызывает _write().

Обратите внимание, что не существует соотношения 1 к 1 между тем, когда потребитель объекта потока вызывает .write(), и когда инфраструктура потока затем вызывает ._write() из-за буферизации внутри объекта потока.

Эта конструкция также позволяет вам иметь один общий интерфейс потока, который может иметь тысячи различных фактических механизмов хранения, в то время как предоставление метода ._write() является одним часть реализации интерфейса хранилища, чтобы предложить общий потоковый интерфейс c для этого хранилища.

...