предисловие
Большое количество API в nodejs связано с потоками.Я видел некоторые коды узлов великих богов компании.Чтобы реализовать интерфейс, вам нужно только подключить другой интерфейс Java. Простая строка кода действительно сбивает с толку. Как и Сяобай, он был сбит с толку, но не осмелился спросить, потому что не знал, с чего начать. Теперь, когда я, наконец, научился, я могу говорить на 123 в потоке и надеюсь общаться с вами.
Введение в потоки
Потоки делятся на буферный режим и объектный режим.Буферный режим может обрабатывать только буферы или строки, а объектный режим может обрабатывать объекты js. Потоки далее делятся на четыре типа: потоки с возможностью чтения, потоки с возможностью записи, дуплексные потоки и потоки преобразования. Последние два на самом деле являются приложениями для чтения и записи потоков. Итак, сначала я хочу поговорить о потоках, доступных для чтения и записи.
читаемый поток
Читаемый поток имеет два режима и может быть преобразован в любое время, мы можем манипулировать им, прослушивая события читаемого потока.
Два режима (цитата из описания узла китайской сети):
1. Режим потока: читаемый поток автоматически считывает данные и как можно быстрее предоставляет данные приложению через события интерфейса EventEmitter.
2. Режим паузы: метод stream.read() должен быть явно вызван для чтения фрагментов данных из потока.
API для переключения из режима паузы в режим потока:
1. Прослушайте событие «данные».
2, вызвать метод stream.resume()
3. Вызовите метод stream.pipe() для отправки данных в доступный для записи поток.
API для переключения из режима потоковой передачи в режим паузы:
1. Если нет цели конвейера, вызовите метод stream.pause()
2. Если есть цель конвейера, вызовите stream.unpipe() и отмените прослушиватель событий «данные».
События читаемого потока: «данные», «читаемый», «ошибка», «закрытие», «конец»
доступный для записи поток
Доступный для записи поток относительно прост, и мы также можем манипулировать им, прослушивая его события.
Доступные для записи события потока: «закрытие», «слив», «ошибка», «завершение», «канал», «удаление канала»
взять каштан
Я описываю наиболее распространенный сценарий стрима на простом примере и рассказываю о понимании этого процесса. Пример: я хочу прочитать файл и записать его содержимое в другой файл (конечно, используя API-интерфейс «stream», а не API-интерфейс модуля «fs»).
Далее поясняю эту картинку:Как показано выше, когда мы создаем доступный для чтения поток, свойство readable._readableState.flowing по умолчанию имеет значение null.На данный момент у нас есть два варианта:
1. Прослушайте событие readable.В это время читаемый поток будет считывать 64 КБ (которые можно изменить через highWaterMark в параметре option при создании читаемого потока) данных в буфер потока, ожидая, пока вы его прочитаете с методом чтения и потреблять данные, когда вы читаете данные размером 64 КБ с помощью метода чтения, событие readable будет запускаться снова, пока вы не прочитаете все данные в исходном файле. Помните, что режим паузы вызывается потому, что если вы не вызовете метод чтения, код всегда будет там останавливаться и ничего не произойдет.
2. Если вы решите прослушать событие «данные», читаемый поток будет напрямую считывать данные размером 64 КБ и предоставлять их вам для использования через функцию обратного вызова события «данные», и этот процесс не остановится. много данных в исходном файле, событие «данные» будет продолжаться до тех пор, пока не будут завершены все чтения. Конечно, вы можете приостановить его в любой момент процесса с помощью метода stream.pause().
Итак, в чем разница между этими двумя режимами? В моем понимании, если вам не нужен точный контроль над данными, сначала выберите режим потока, потому что он более эффективен. Режим паузы можно выбрать, если требуется точный контроль над ходом потока. То есть режим паузы — это более продвинутое использование потоковой передачи. На самом деле, официальная рекомендация заключается в том, что мы стараемся не управлять потоком вручную, по возможности стараемся использовать метод пайпа.
Далее, независимо от того, каким образом мы читаем данные в файле, мы можем создать доступный для записи поток и вызвать метод записи доступного для записи потока для использования прочитанных данных. Вызов метода записи запишет данные в файл, но из-за низкой скорости записи, если текущая запись все еще продолжается, и вы снова вызываете метод записи, узел кэширует данные, которые вы хотите записать, в буферной области. файл записывается, данные будут извлечены из области буфера и будут продолжать записываться.
Метод записи имеет возвращаемое значение логического типа, которое используется для указания, можно ли продолжать вызывать метод записи для записи содержимого. Если он возвращает false, мы должны прекратить чтение данных, чтобы не потреблять слишком много памяти. Итак, когда он вернет false? То есть когда размер области буфера больше 16k (что можно изменить через highWaterMark в параметре option при создании читаемого потока).
После заполнения области буфера происходит запись файла, и все содержимое области буфера будет записано в течение короткого времени, а область буфера находится в пустом состоянии.В это время происходит событие «слив». будет запущен доступный для записи поток. В это время мы можем продолжить запись в файл. Данные записываются. Примечание. Если буфер никогда не заполняется, событие «слив» никогда не сработает.
Так что же соответствует этой картинке код:
let fs = require('fs');
//创建可读可写流
let rs = fs.createReadStream('./1.txt');
let ws = fs.createWriteStream('./2.txt');
//监听‘data’事件,开启流动模式
rs.on('data',function (data) {
//对应图中的可写流true和false
let flag = ws.write(data);
if(!flag){
//如果可写流返回false,我们应当停止读取,以避免消耗过多内存
rs.pause();
}
});
//对应图中的drain事件
ws.on('drain',function () {
//重新开启流动模式
rs.resume();
});
//使用可读流的暂停模式
function read() {
let data = rs.read()
let flag = ws.write(data);
if(flag){
read()
}
}
rs.on('readable',function(){
read()
})
ws.on('drain',function () {
read()
});
конец
Существует множество вариантов использования и API для чтения и записи потоков. Вот лишь краткий обзор основного процесса. Если в описании есть какие-либо неточности, поправьте меня в комментариях.
использованная литература
- https://nodejs.org/dist/latest-v8.x/docs/api/stream.html
- http://nodejs.cn/api/