1. Вступительный анализ
Поток - это абстрактный интерфейс, реализованный многими объектами в узле. Например, запрос на HTTP -сервер - это поток, а Stdout также является потоком. Потоки читаемые, записываются или оба.
Первый контакт с потоком начался с раннего UNIX. Десятилетия практики доказали, что идея потока может просто разработать некоторые огромные системы.
В UNIX поток реализуется через «|». В узле, в качестве модуля встроенного потока, используются многие основные модули и трехпартийные модули.
Как и Unix, основная операция потока узлов составляет .pipe (), и пользователи могут использовать механизм контрприкосновения для управления балансом между чтением и записи.
Поток может предоставить разработчикам унифицированный интерфейс, который может повторно использовать и контролировать баланс чтения и записи между потоками через абстрактные интерфейсы потока.
Соединение TCP - это как читаемый поток, так и потоковой записи, в то время как HTTP -соединение отличается. Объект HTTP -запроса - это читаемый поток, в то время как объект ответа HTTP является записью для записи.
Процесс передачи потока передается в форме буфера по умолчанию, если только вы не установите для него другие формы кодирования, приведен пример:
Кода -копия выглядит следующим образом:
var http = require ('http');
var server = http.createserver (function (req, res) {
res.writeheader (200, {'content-type': 'text/plain'});
res.end ("Привет, большой медведь!");
});
Server.Listen (8888);
console.log ("http -сервер, работающий на порту 8888 ...");
После запуска появится искаженный код, потому что указанный набор символов не установлен, например: «UTF-8».
Просто измените его:
Кода -копия выглядит следующим образом:
var http = require ('http');
var server = http.createserver (function (req, res) {
res.writeheader (200, {
'' Content-Type ':' Text/plain; charset = utf-8 '// add charset = utf-8
});
res.end ("Привет, большой медведь!");
});
Server.Listen (8888);
console.log ("http -сервер, работающий на порту 8888 ...");
Результаты работы:
Зачем использовать поток
Ввод/вывод в узле является асинхронным, поэтому чтение и написание на диск и сеть требует чтения и чтения данных с помощью функций обратного вызова. Ниже приведен пример загрузки файла
На коде:
Кода -копия выглядит следующим образом:
var http = require ('http');
var fs = require ('fs');
var server = http.createserver (function (req, res) {
fs.readfile (__ dirname + '/data.txt', function (err, data) {
res.end (data);
});
});
Server.Listen (8888);
Код может реализовать требуемые функции, но служба должна кэшировать все данные файла в память перед отправкой данных файла. Если файл "data.txt" очень
Если он большой и имеет большую параллелизм, много памяти будет потрачено впустую. Поскольку пользователю необходимо подождать, пока весь файл кэшируется в памяти, чтобы принять данные файла, это приводит к
Пользовательский опыт довольно плохой. К счастью, оба параметра (REQ, RES) являются потоком, поэтому мы можем использовать fs.createreadStream () вместо fs.readfile (). следующее:
Кода -копия выглядит следующим образом:
var http = require ('http');
var fs = require ('fs');
var server = http.createserver (function (req, res) {
var stream = fs.createreadstream (__ dirname + '/data.txt');
stream.pipe (res);
});
Server.Listen (8888);
Метод .pipe () прослушивает события «данные» и «конец» fs.createreadstream (), так что файл «data.txt» не нуждается в кэшировании.
Файл может быть отправлен клиенту сразу после завершения подключения клиента. Еще одно преимущество использования .pipe () заключается в том, что его можно решить, когда клиент
Читайте и пишите дисбаланс, вызванный очень большой конечной задержкой.
Есть пять основных потоков: читаемые, записываемые, преобразование, дуплекс и «классический». (Пожалуйста, проверьте API для получения подробной информации)
2. Представьте примеры
Когда данные, которые необходимо обрабатывать, не могут быть загружены в памяти за один раз или когда обработка более эффективна при чтении, нам необходимо использовать потоки данных. Nodejs предоставляет операции по потокам данных через различные потоки.
Принимая большую программу копирования файлов в качестве примера, мы можем создать поток данных только для чтения для источника данных, пример заключается в следующем:
Кода -копия выглядит следующим образом:
var rs = fs.createreadstream (pathname);
rs.on ('data', function (chunk) {
что -то (кусок); // Используйте конкретные детали, как вы хотите
});
rs.on ('end', function () {
очистка ();
});
События данных в коде будут инициированы непрерывно, независимо от того, может ли функция DOSomething быть обработана. Код может быть изменен следующим образом для решения этой проблемы.
Кода -копия выглядит следующим образом:
var rs = fs.createreadstream (src);
rs.on ('data', function (chunk) {
rs.pause ();
Dosomhething (Chunk, function () {
Rs.Resume ();
});
});
rs.on ('end', function () {
очистка ();
});
Обратный вызов добавляется в функцию Dosomething, поэтому мы можем приостановить чтение данных перед обработкой данных и продолжать читать данные после обработки данных.
Кроме того, мы также можем создать поток данных только для записи для цели данных, следующим образом:
Кода -копия выглядит следующим образом:
var rs = fs.createreadstream (src);
var ws = fs.createwritestream (dst);
rs.on ('data', function (chunk) {
ws.write (кусок);
});
rs.on ('end', function () {
ws.end ();
});
После того, как что-то заменено, написав данные в потоку только для записи, приведенный выше код выглядит как программа копирования файла. Тем не менее, приведенный выше код имеет проблемы, упомянутые выше. Если скорость записи не может идти в ногу со скоростью чтения, только написание кэша внутри потока данных взорвется. Мы можем судить, были ли входящие данные записаны в цель или временно размещены в кэше на основе возврата значения метода .WRITE, и судья, когда только данные о записи были записаны в цель на основе события дренажа, и передают следующие данные, которые будут записаны. Поэтому код выглядит следующим образом:
Кода -копия выглядит следующим образом:
var rs = fs.createreadstream (src);
var ws = fs.createwritestream (dst);
rs.on ('data', function (chunk) {
if (ws.write (chunk) === false) {
rs.pause ();
}
});
rs.on ('end', function () {
ws.end ();
});
ws.on ('Drain', function () {
Rs.Resume ();
});
Наконец, передача данных из потока данных только для чтения в поток данных только для записи реализован, и включено управление складом, защищенное от взрыва. Поскольку существует множество сценариев использования, таких как вышеуказанная программа копирования большой файла, Nodejs напрямую предоставляет метод .pipe для этого, а его метод внутренней реализации аналогичен вышеуказанному коду.
Вот более полный процесс копирования файлов:
Кода -копия выглядит следующим образом:
var fs = require ('fs'),
path = require ('path'),
out = process.stdout;
var filePath = '/bb/bigbear.mkv';
var readstream = fs.createreadStream (filePath);
var writestream = fs.createwritestream ('file.mkv');
var stat = fs.statsync (filepath);
var totalsize = stat.size;
var прошедла длину = 0;
var длится = 0;
var startTime = date.now ();
readstream.on ('data', function (chunk) {
Продолжительная длина += chunk.length;
if (writestream.write (chunk) === false) {
readstream.pause ();
}
});
readstream.on ('end', function () {
writestream.end ();
});
writestream.on ('drain', function () {
readstream.resume ();
});
settimeout (function show () {
var penest = math.ceil ((передача длины / totalsize) * 100);
var size = math.ceил (передача длины / 1000000);
var diff = size - lastize;
Продолжительность = размер;
out.clearline ();
out.cursorto (0);
out.write ('завершен' + size + 'mb,' + процент + '%, скорость:' + diff * 2 + 'mb/s');
if (прошедшая длина <totalsize) {
SetTimeout (Show, 500);
} еще {
var EndTime = date.now ();
console.log ();
console.log ('Когда общий:' + (endtime - starttime) / 1000 + 'секунд.');
}
}, 500);
Вы можете сохранить приведенный выше код как "copy.js". Эксперимент: мы добавили рекурсивную установку (или непосредственно использовать SetInterval), чтобы стать свидетелем.
Соблюдайте прогресс завершения каждые 500 мс и записывайте завершенный размер, процент и скорость копирования в консоли. При завершении копирования общее время рассчитывается.
Три, давайте обобщусь
(1) Понять концепцию потока.
(2) Опыт в использовании соответствующего потокового API
(3) Обратите внимание на управление деталями, такими как: копирование больших файлов, используя форму «Chunk Data» для шардинга.
(4), использование трубы
(5), еще раз подчеркните концепцию: соединение TCP - это как читаемый поток, так и поток для записи, в то время как HTTP -соединение отличается. Объект HTTP -запроса - это читаемый поток, в то время как объект ответа HTTP является записью для записи.