Если вы хотите изучить Node.js, сначала необходимо понять поток.

Node.js JavaScript
Если вы хотите изучить Node.js, сначала необходимо понять поток.

что такое стрим

определение

Английский потокstream, Stream — это абстрактный интерфейс данных,Node.jsМногие объекты в потоке реализуют потоки, а потокиEventEmitterЭкземпляр объекта, который в любом случае принимает форму данных (сBufferединиц) или что-то, что поглощает данные, что, по сути, заставляет их течь. Может быть, будет более интуитивно смотреть на картинку:

水桶管道流转图

Уведомление:streamЭто не уникальная концепция node.js, а самый простой метод работы операционной системы, но у node.js есть API для поддержки этого метода работы. команда Linux |stream.

Об авторе: koala, сосредоточив внимание на совместном использовании полного стека технологий Node.js, от JavaScript до Node.js, до серверной базы данных, я желаю вам стать отличным старшим инженером Node.js. [Руководство по развитию программиста] Автор, блог Github с открытым исходным кодомGitHub.com/koala-co Nth…

Зачем изучать стримы

Пример воспроизведения видео

Маленькие друзья наверняка видели фильм онлайн, сравните картинку в определении-水桶管道流转图,sourceЭто серверное видео.destПросто свой плеер (или flash и h5 видео в браузере). Подумайте об этом, способ просмотра фильма похож на замену воды в трубе на картинке выше.Видео передается с сервера на локальный проигрыватель по крупицам, воспроизводится во время потоковой передачи и заканчивается, когда трансляция завершена.

Описание: В этом примере воспроизведения видео, если мы не используем метод конвейера и потоковой передачи, видеофайл загружается непосредственно с сервера, а затем воспроизводится. вызовет много проблем

  1. Система зависает или дает сбой из-за слишком большого использования памяти
  2. Поскольку скорость нашей сети, память и скорость работы процессора ограничены, а также существует несколько программ для совместного использования и использования, размер видеофайла после загрузки может достигать нескольких гигабайт.

Пример чтения данных большого файла

Есть такое требование, пример желания прочитать большой файл data

читать с помощью файла

const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer(function (req, res) {
    const fileName = path.resolve(__dirname, 'data.txt');
    fs.readFile(fileName, function (err, data) {
        res.end(data);
    });
});
server.listen(8000);

Используйте этот файлы синтаксиса кода для чтения, и нет проблем, но если файл data.txt очень большой, к сотням m, когда пользователь в ответ на большое количество одновременных запросов, программа может потреблять большие суммы Память, которая может привести к тому, что пользователи проблему медленного подключения. И одновременный запрос слишком велик, накладные расходы на серверу будут отличными. На этот раз мы смотрим наstreamвыполнить.

const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer(function (req, res) {
    const fileName = path.resolve(__dirname, 'data.txt');
    let stream = fs.createReadStream(fileName);  // 这一行有改动
    stream.pipe(res); // 这一行有改动
});
server.listen(8000);

Используя поток, вам не нужно читать все файлы, а затем возвращать, а возвращать во время чтения, и данные поступают к клиенту через конвейер, что действительно снижает нагрузку на сервер.

Прочитав два примера, я думаю, что мои друзья должны знать, что什么要使用streamНу давай же! Поскольку чтение и работа с большими файлами одновременно, память и сеть невыносимы, поэтому позвольте данным течь и работать понемногу.

потоковый процесс

посмотри на это снова水桶管道流转图

水桶管道流转图
Как можно увидеть на фиг,streamВесь процесс потока включает в себя источник, место назначения и конвейер, соединяющий их (ядро потока) Три представлены отдельно, чтобы помочь вам понять поток процесса потока.

откуда берется поток - soucre

streamЕсть три распространенных источника:

  1. ввод из консоли
  2. httpв запросеrequest
  3. прочитать файл

Здесь сначала从控制台输入Таким образом, 2 и 3 два путиstream应用场景Главы объяснят подробно.

смотреть абзацprocess.stdinкод

process.stdin.on('data', function (chunk) {
    console.log('stream by stdin', chunk)
    console.log('stream by stdin', chunk.toString())
})
//控制台输入koalakoala后输出结果
stream by stdin <Buffer 6b 6f 61 6c 61 6b 6f 61 6c 61 0a>
stream by stdin koalakoala

Запустите приведенный выше код: тогда все, что будет введено с консоли, будетdataсобытие отслеживается,process.stdinтолько одинstreamобъект, данные даstreamПользовательская функция, которую объект использует для мониторинга входящих данных, которые можно увидеть на выходе.process.stdinявляется потоковым объектом.

проиллюстрировать:streamОбъект может слушать"data","end","opne","close","error"и т.д. события.node.jsСлушайте пользовательские события, используя.onМетод, например,process.stdin.on(‘data’,…), req.on(‘data’,…), таким образом, очень интуитивно понятно контролироватьstreamвходящие и исходящие данные

Труба, соединяющая ковш с трубой

Как видно из схемы работы ковшового трубопровода, вsourceа такжеdestМежду ними имеется соединительная трубка.pipe, его основной синтаксисsource.pipe(dest),sourceа такжеdestЭто подключение через канал и передача данных изsourceтечь кdest.

куда идет поток -dest

Общий выходной поток тремя способами:

  1. консоль вывода
  2. httpв запросеresponse
  3. записать в файл

потоковые сценарии приложений

streamСценарий приложения в основном касаетсяIOоперация, при этомhttp请求а также文件操作принадлежатьIOработать. Снова здесьstreamхарактер - за счет одноразовогоIOОперация слишком велика, а накладные расходы на оборудование слишком велики, что влияет на эффективность работы программного обеспечения.IOРаботайте пакетами и сегментами, и пусть данные текут, как водопровод, пока поток не будет завершен, то есть операция не будет завершена. Ниже представлено несколько распространенных сценариев применения.

Представляем небольшой инструмент для стресс-тестирования

Инструмент для нагрузочного тестирования сетевых запросовab,abполное имяApache bench,ДаApacheпоставляется с инструментом, поэтому используйтеabдолжен быть установленApache. система mac os поставляется сApache,windows用户视自己的情况进行安装。 бегатьabначать раньшеApache,mac osСпособ начатьsudo apachectl start.

Подробный адрес изучения соответствующих параметров стенда Apache, вы можете посмотреть, если вам интересноПодробный адрес изучения соответствующих параметров стенда Apache

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

Применить поток в запросе на получение

Такое требование:

Используйте node.js для реализации HTTP-запроса, чтения файла data.txt, создания службы, прослушивания порта 8000, чтения файла и возврата его клиенту.Говоря о запросах на получение, используйте обычный файл для чтения и сравнения это, см. пример ниже.

  • Регулярное использование чтения файла и возврат к примеру ответа клиента, файл называется какgetTest1.js
// getTest.js
const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer(function (req, res) {
    const method = req.method; // 获取请求方法
    if (method === 'GET') { // get 请求方法判断
        const fileName = path.resolve(__dirname, 'data.txt');
        fs.readFile(fileName, function (err, data) {
            res.end(data);
        });
    }
});
server.listen(8000);
  • Используйте поток, чтобы вернуть ответ клиенту Внесите некоторые изменения в приведенный выше код и назовите файл какgetTest2.js
// getTest2.js
// 主要展示改动的部分
const server = http.createServer(function (req, res) {
    const method = req.method; // 获取请求方法
    if (method === 'GET') { // get 请求
        const fileName = path.resolve(__dirname, 'data.txt');
        let stream = fs.createReadStream(fileName);
        stream.pipe(res); // 将 res 作为 stream 的 dest
    }
});
server.listen(8000);

Для примера использования потока в запросе на получение ниже, некоторые мелкие партнеры зададут вопрос, является ли ответ также объектом потока, да, да, для этого水桶管道流转图, ответ - это дест.

Хотя потоки могут использоваться в запросах на получение, по сравнению с прямым чтением файлов·res.end(data)Каковы преимущества? В настоящее время используется гаджет стресс-теста, который мы только что рекомендовали.getTest1а такжеgetTest2два фрагмента кода, которыеdata.txtЧтобы увеличить содержимое, используйтеabинструмент для тестирования, запустите командуab -n 100 -c 100 http://localhost:8000/-n 100Указывает, что последовательно отправлено 100 запросов,-c 100Указывает, что количество запросов, отправленных за один раз, равно 100. Сравнив результаты и проанализировав использование потоковой передачи, можно увидеть очень большое улучшение производительности, и друзья могут это увидеть сами.

использовать стрим в посте

Требование генерировать QR-код через сообщение, запрашивающее адрес апплета WeChat.

/*
* 微信生成二维码接口
* params src 微信url / 其他图片请求链接
* params localFilePath: 本地路径
* params data: 微信请求参数
* */
const downloadFile=async (src, localFilePath, data)=> {
    try{
        const ws = fs.createWriteStream(localFilePath);
        return new Promise((resolve, reject) => {
            ws.on('finish', () => {
                resolve(localFilePath);
            });
            if (data) {
                request({
                    method: 'POST',
                    uri: src,
                    json: true,
                    body: data
                }).pipe(ws);
            } else {
                request(src).pipe(ws);
            }
        });
    }catch (e){
        logger.error('wxdownloadFile error: ',e);
        throw e;
    }
}

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

Публикуйте и используйте резюме потока

Запрос и ответ являются объектами потока и могут использовать характеристики потока. Разница между ними заключается в том, что давайте посмотрим水桶管道流转图,

Запрос является исходным типом, который является источником на диаграмме, а ответ — типом получателя, который является пунктом назначения на диаграмме.

Использование потоков в файловых операциях

Пример копии файла

const fs = require('fs')
const path = require('path')

// 两个文件名
const fileName1 = path.resolve(__dirname, 'data.txt')
const fileName2 = path.resolve(__dirname, 'data-bak.txt')
// 读取文件的 stream 对象
const readStream = fs.createReadStream(fileName1)
// 写入文件的 stream 对象
const writeStream = fs.createWriteStream(fileName2)
// 通过 pipe执行拷贝,数据流转
readStream.pipe(writeStream)
// 数据读取完成监听,即拷贝完成
readStream.on('end', function () {
    console.log('拷贝完成')
})

Прочитав этот код, я обнаружил, что копирование кажется очень простым, создавая читаемый поток данных.readStream, Доступный для записи поток данныхwriteStream, а затем напрямую черезpipeПо каналам проходят данные. Этот вид копирования с использованием потока имеет гораздо более высокую производительность, чем реализация чтения-записи файлового хранилища, поэтому, когда вы столкнетесь с потребностями файловых операций, постарайтесь оценить, нужно ли вам его использовать.streamвыполнить.

Базовая реализация некоторых интерфейсных инструментов упаковки

Некоторые из самых горячих前端打包构建工具, на всем протяженииnode.jsПроцесс написания, упаковки и сборки должен быть процессом частых манипуляций с файлами, неотделимым отstream, например, сейчас популярнееgulp, Заинтересованные друзья могут взглянуть на исходный код.

Вид потока

  • Readable Streamчитаемый поток данных
  • Writeable Streamдоступный для записи поток данных
  • Duplex StreamДвунаправленный поток данных, может читать и писать одновременно
  • Transform StreamПреобразовывать поток данных, доступный для чтения и записи, и может преобразовывать (обрабатывать) данные (обычно не используется)

Предыдущие статьи были посвящены первым двум потокам данных для чтения и потокам данных для записи. Четвертый поток обычно не используется. Если он вам нужен, выполните поиск в Интернете. Далее я объясню третий поток данных, дуплексный поток.

Duplex StreamДвунаправленный, как для чтения, так и для записи.Duplex streamsВ то же время понялReadableа такжеWritableинтерфейс.Duplex streamsПримеры включают

  • tcp sockets
  • zlib streams
  • crypto streamsЯ не использовал дуплексные потоки в своем проекте, вы можете обратиться к этой статье за ​​некоторым содержимым дуплексного потока.Дуплексный поток NodeJS Stream

В чем недостатки стрима

  • использоватьrs.pipe(ws)способ записать файл вместо помещения содержимого rsappendПерейти к задней части ws, но напрямую перезаписать исходное содержимое ws содержимым rs
  • Завершенные/закрытые потоки нельзя использовать повторно, поток данных необходимо создать заново
  • pipeМетод возвращает целевой поток данных, напримерa.pipe(b)Возврат - b, поэтому обратите внимание на то, является ли объект, который вы слушаете, правильным при прослушивании события.
  • Если вы хотите прослушивать несколько потоков данных одновременно и используетеpipeметод объединения потоков данных, вы должны написать: Пример кода:
 data
        .on('end', function() {
            console.log('data end');
        })
        .pipe(a)
        .on('end', function() {
            console.log('a end');
        })
        .pipe(b)
        .on('end', function() {
            console.log('b end');
        });

Общая библиотека классов для потока

  • event-stream Похоже на функциональное программирование

  • awesome-nodejs#streamsЭто также хорошая сторонняя библиотека для потоковой передачи. Заинтересованные партнеры могут заглянуть на github.

Суммировать

После прочтения этой статьи у вас появилось определенное представление о потоке и вы знаете, что у узла все еще есть идеальное решение для обработки файлов. Эта бумага показывает три раза水桶管道流转图, Трижды произнесите то, что вы всегда хотите, и надейтесь, что друзья это запомнят.

  1. Каково конкретное содержание потокового потока данных? двоичный илиstringтип или что-то еще, какую пользу приносит этот тип для стрима?
  2. Водопровод на схеме ковшовой трубы, т.е.pipeКогда срабатывает функция? При каких обстоятельствах осуществляется переадресация сенсорного потока? Каков основной механизм? Приведенные выше вопросы (разделенные на две статьи из-за объема статьи) будут обсуждаться в моемstreamВторая статья объяснит подробно.

Так много, чем можно поделиться сегодня.Если вы заинтересованы в общем контенте, вы можете подписаться на официальную учетную запись «Руководство по развитию программиста» или присоединиться к группе технического обмена, чтобы обсудить его вместе.

Присоединяйтесь к нам, чтобы учиться вместе!

группа обмена обучением узлов

Если группа обмена состоит из 100 человек, она не может автоматически присоединиться к группе.Пожалуйста, добавьте учетную запись WeChat помощника группы: узел [coder_qi] Note, и он автоматически втянет вас в группу.