Rumah > hujung hadapan web > tutorial js > Node kajian Nodejs Strim module_node.js

Node kajian Nodejs Strim module_node.js

WBOY
Lepaskan: 2016-05-16 16:20:27
asal
1361 orang telah melayarinya

1, analisis pembukaan

Strim ialah antara muka abstrak yang dilaksanakan oleh banyak objek dalam Node. Sebagai contoh, permintaan kepada pelayan HTTP ialah strim, dan stdout juga merupakan strim. Strim boleh dibaca, boleh ditulis atau kedua-duanya.

Pendedahan terawal kepada Strim bermula pada hari-hari awal pengamalan Unix selama beberapa dekad telah membuktikan bahawa idea Strim boleh membangunkan beberapa sistem yang besar dengan mudah.

Dalam Unix, Stream dilaksanakan melalui "|". Dalam nod, sebagai modul strim terbina dalam, banyak modul teras dan modul pihak ketiga digunakan.

Seperti Unix, operasi utama aliran nod juga ialah .pipe().

Strim boleh menyediakan pembangun antara muka bersatu yang boleh digunakan semula dan mengawal keseimbangan baca dan tulis antara strim melalui antara muka Strim abstrak.

Sambungan TCP ialah strim boleh dibaca dan strim boleh tulis, manakala sambungan HTTP adalah berbeza Objek permintaan http ialah strim boleh dibaca dan objek tindak balas http ialah strim boleh ditulis.

Proses penghantaran strim dihantar dalam bentuk penimbal secara lalai, melainkan anda menetapkan kaedah pengekodan lain untuknya. Berikut ialah contoh:

Salin kod Kod adalah seperti berikut:

var http = memerlukan('http') ;
pelayan var = http.createServer(function(req,res){
res.writeHeader(200, {'Content-Type': 'text/plain'}) ;
res.end("Hello, Beruang Besar!") ;
}) ;
server.listen(8888) ;
console.log("Pelayan http berjalan pada port 8888...") ;

Aksara bercelaru akan muncul selepas dijalankan Sebabnya ialah set aksara yang ditentukan tidak ditetapkan, seperti: "utf-8".

Hanya ubah suai:

Salin kod Kod adalah seperti berikut:

var http = memerlukan('http') ;
pelayan var = http.createServer(function(req,res){
res.writeHeader(200,{
         'Content-Type' : 'text/plain;charset=utf-8' // Tambah charset=utf-8
}) ;
res.end("Hello, Beruang Besar!") ;
}) ;
server.listen(8888) ;
console.log("Pelayan http berjalan pada port 8888 ...") ;

Hasil jalankan:

Mengapa menggunakan Strim
I/O dalam nod adalah tak segerak, jadi membaca dan menulis ke cakera dan rangkaian memerlukan fungsi panggil balik untuk membaca data Berikut ialah contoh muat turun fail
Kod di atas:

Salin kod Kod adalah seperti berikut:

var http = memerlukan('http') ;
var fs = memerlukan('fs') ;
pelayan var = http.createServer(fungsi (req, res) {
fs.readFile(__dirname '/data.txt', fungsi (err, data) {
           res.end(data);
}) ;
}) ;
server.listen(8888) ;

Kod boleh mencapai fungsi yang diperlukan, tetapi perkhidmatan perlu menyimpan keseluruhan data fail ke dalam memori sebelum menghantar data fail Jika fail "data.txt" sangat besar
Jika ia besar dan jumlah concurrency adalah besar, banyak memori akan terbuang. Kerana pengguna perlu menunggu sehingga keseluruhan fail dicache dalam memori sebelum menerima data fail, ini menghasilkan
Pengalaman pengguna agak teruk. Nasib baik, kedua-dua parameter (req, res) ialah Strim, jadi kita boleh menggunakan fs.createReadStream() dan bukannya fs.readFile(). Seperti berikut:

Salin kod Kod adalah seperti berikut:

var http = memerlukan('http') ;
var fs = memerlukan('fs') ;
pelayan var = http.createServer(fungsi (req, res) {
var stream = fs.createReadStream(__dirname '/data.txt') ;
Stream.pipe(res) ;
}) ;
server.listen(8888) ;

Kaedah.pipe() mendengar peristiwa 'data' dan 'end' fs.createReadStream(), supaya fail "data.txt" tidak perlu dicache secara keseluruhannya
fail, blok data boleh dihantar kepada klien serta-merta selepas sambungan klien selesai. Satu lagi faedah menggunakan .pipe() ialah ia boleh menyelesaikan masalah apabila pelanggan
Masalah ketidakseimbangan baca-tulis disebabkan oleh kependaman hujung ke hujung yang sangat besar.

Terdapat lima Strim asas: boleh dibaca, boleh ditulis, diubah, dupleks dan "klasik". (Sila semak API untuk penggunaan khusus)

2. Pengenalan contoh

Apabila data yang perlu diproses tidak dapat dimuatkan dalam memori pada satu masa, atau apabila ia lebih cekap untuk membaca dan memproses pada masa yang sama, kita perlu menggunakan aliran data. NodeJS menyediakan operasi pada aliran data melalui pelbagai Aliran.

Mengambil program penyalinan fail besar sebagai contoh, kami boleh mencipta strim data baca sahaja untuk sumber data Contohnya adalah seperti berikut:

Salin kod Kod adalah seperti berikut:

var rs = fs.createReadStream(pathname);
rs.on('data', fungsi (chunk) {
doSomething(chunk); // Jangan ragu untuk bermain dengan butiran
});
rs.on('end', function () {
       cleanUp() ;
}) ;

Peristiwa data dalam kod akan dicetuskan secara berterusan, tidak kira sama ada fungsi doSomething boleh mengendalikannya. Kod boleh terus diubah suai seperti berikut untuk menyelesaikan masalah ini.

Salin kod Kod adalah seperti berikut:

var rs = fs.createReadStream(src) ;
rs.on('data', fungsi (chunk) {
​ rs.pause() ;
doSomething(chunk, function () {
          rs.resume() ;
}) ;
}) ;
rs.on('end', function () {
       cleanUp();
}) ;

Panggilan balik ditambahkan pada fungsi doSomething supaya kami boleh menjeda bacaan data sebelum memproses data dan meneruskan membaca data selepas memproses data.

Selain itu, kami juga boleh mencipta aliran data tulis sahaja untuk sasaran data, seperti berikut:

Salin kod Kod adalah seperti berikut:

var rs = fs.createReadStream(src) ;
var ws = fs.createWriteStream(dst) ;
rs.on('data', fungsi (chunk) {
            ws.write(chunk);
}) ;
rs.on('end', function () {
          ws.end();
}) ;

Selepas doSomething digantikan dengan menulis data ke dalam aliran data tulis sahaja, kod di atas kelihatan seperti program penyalinan fail. Walau bagaimanapun, kod di atas mempunyai masalah yang dinyatakan di atas Jika kelajuan menulis tidak dapat bersaing dengan kelajuan membaca, cache dalam aliran data tulis sahaja akan pecah. Kami boleh menggunakan nilai pulangan kaedah .write untuk menentukan sama ada data masuk ditulis kepada sasaran atau diletakkan sementara dalam cache dan berdasarkan peristiwa longkang, kami boleh menentukan apabila aliran data tulis sahaja telah menulis data dalam cache ke sasaran , data seterusnya yang akan ditulis boleh dihantar masuk. Jadi kodnya adalah seperti berikut:

Salin kod Kod adalah seperti berikut:

var rs = fs.createReadStream(src) ;
var ws = fs.createWriteStream(dst) ;
rs.on('data', fungsi (chunk) {
Jika (ws.write(chunk) === palsu) {
          rs.pause() ;
}
}) ;
rs.on('end', function () {
          ws.end();
});
ws.on('longkang', fungsi () {
​ rs.resume();
}) ;

Akhirnya menyedari pemindahan data daripada aliran data baca sahaja kepada aliran data tulis sahaja, dan termasuk kawalan gudang kalis letupan. Oleh kerana terdapat banyak senario penggunaan untuk ini, seperti program penyalinan fail besar di atas, NodeJS secara langsung menyediakan kaedah .pipe untuk melakukan ini dan pelaksanaan dalamannya adalah serupa dengan kod di atas.

Berikut ialah proses menyalin fail yang lebih lengkap:

Salin kod Kod adalah seperti berikut:

var fs = memerlukan('fs'),
  laluan = memerlukan('path'),
  keluar = 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 passedLength = 0;
var lastSize = 0;
var startTime = Date.now();
readStream.on('data', function(chunk) {
  passedLength = ketul.panjang;
  if (writeStream.write(chunk) === false) {
    readStream.pause();
  }
});
readStream.on('end', function() {
  writeStream.end();
});
writeStream.on('drain', function() {
  readStream.resume();
});
setTimeout(function show() {
  var peratus = Math.ceil((passedLength / totalSize) * 100);
  saiz var = Math.ceil(passedLength / 1000000);
  var diff = saiz - lastSize;
  lastSize = saiz;
  out.clearLine();
  out.cursorTo(0);
  out.write('已完成' saiz 'MB, ' peratus '%, 速度:' diff * 2 'MB/s');
  jika (melepasiPanjang < jumlahSaiz) {
    setTimeout(tunjukkan, 500);
  } lain {
    var endTime = Date.now();
    console.log();
    console.log('共用时:' (masa tamat - masa mula) / 1000 '秒。');
  }
}, 500);

可以把上面的代码保存为 "copy.js" 试验一下我们添加了一个递归的 setTimeout (戴睔掅set(戴睔厅set一个旁观者,

每500ms观察一次完成进度,并把已完成的大小、百分比和复制速度一并把已完成的大小、百分比和复制速度一尶厙制小完成时,计算总的耗费时间。

三,总结一下

(1),理解Stream概念。

(2),熟练使用相关Strim的api

(3),注意细节的把控,比如:大文件的拷贝,采用的使用 “data cebisan” 的形式进行分片。

(4),paip的使用

(5),再次强调一个概念:一个TCP连接既是可读流,又是可写流,而Http吿中心中可一接是可读流,而http respon对象则是可写流。

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan