node.js Stream


Streamは抽象的なインターフェースで、Nodeの中に多くのオブジェクトがこのインターフェースを実現しました.例えば、httpサーバに対して要求を開始するrequestオブジェクトは、Streamであり、stdout(標準出力)である.
流れは何ですか
流れはNode.jsアプリケーションに動力を提供する基本概念の一つである.
これらは、ファイルの読み書き、ネットワーク通信、または任意の種類のエンドツーエンドを効率的に処理するための情報交換である.
例えば、従来の方式では、プログラムにファイルの読み取りを教えると、ファイルは最初から最後までメモリに読み込まれて処理されます.ストリームを使用すると、メモリ全体に保存することなく、1つずつのフラグメントを読み出して処理することができる.
Node.jsのstreamモジュールは、すべてのストリームAPIを構築するための基礎を提供する.全ての流れはEventEmitterの例です.
const {
      createServer } = require('http')
const {
      resolve } = require('path')
const {
      readFile, createReadStream } = require('fs')

createServer((req, res) => {
     
  if (req.url === '/favicon.ico') {
     
    res.writeHead(200)
  } else if (req.url === '/') {
     
    //         ,      ,      
    res.writeHead(200, {
     
      'Content-Type': 'text/html; charset=utf-8'
    })
    const stream = createReadStream(resolve(__dirname, 'home.html'))
    //    pipe           
    stream.pipe(res)

  } else if (req.url === '/about') {
     
    //      ,         ,    。      ,            。
    readFile(resolve(__dirname, 'about.html'), 'utf-8', (err, data) => {
     
      if (err) return
      res.writeHead(200, {
     
        'Content-Type': 'text/html; charset=utf-8'
      })
      res.write(data)
      //        ,   res.end       
      res.end()
    })
  } else {
     
    res.statusCode = 404
    res.end()
  }
})
  .listen(3000, () => {
     
    console.log('http://localhost:3000');
  })
Streamの種類
  • Readable-読み取り可能な動作.パイプを通して読み取ることができますが、ダクトを通して書き込まれないストリーム(データは受信できますが、データは送信できません).読み取り可能なストリームにデータを転送すると、使用者がデータを読み始めるまでバッファリングされます.
  • Writable-書き込み可能操作.
  • Duplex−読み書き可能動作.
  • Transform−動作がデータに書き込まれ、結果が読み出される.
  • この前にnodeのEventEmitterをまとめました.すべてのStreamオブジェクトはEventEmitterの実例であるので、彼らは自分で定義した一連のイベントがあります.
  • data-データ読み取り可能なときにトリガされる.
  • end-より多くのデータが読み取り可能でないときにトリガする.
  • error-受信および書込み中にエラーが発生した場合にトリガする.
  • finish-すべてのデータが最終層システムに書き込まれたときにトリガされる.
  • 読み取り可能なストリームの2つのモード
  • flowingは、flowingモードで、読み取り可能なストリームが自動的にシステムの下からデータを読み取り、EventEmitterインターフェースのイベントを通じて、できるだけ早くデータをアプリケーションに提供する.
  • pausedは、pausedモードで、ストリームからデータセグメントを読み取るために、stream.read(stread)方法を明示的に起動しなければならない.
  • 両モード間の切り替え
    すべての初期動作モードはpausedのReadableストリームであり、次の3つの方法でflowingモードに切り替えることができる.
    ストリームは、デフォルトの一時停止モードからフローモードに切り替わるために、以下のいくつかの方法を使用することができる.
  • データ傍受器を追加することにより、データ傍受
  • を起動する.
  • .データストリームを起動するための方法論を起動する
  • .
  • pipe()方法を呼び出して、他の書き込み可能ストリーム
  • にデータを転送する.
    フローモードから一時停止モードに切り替える他の2つの方法:
  • は、ストリームがpipe()がない場合、pause()を呼び出す方法で、ストリームを一時停止することができる
  • .
  • pipe()の場合、dataイベントのすべての傍受を除去し、unpipe()方法
  • を呼び出します.
    単純な例で、読み取り可能なストリームを作成します.
    const {
          Readable, Writable } = require('stream')
    
    const readStream = new Readable({
         
      /**
       * Readable       _read      ,_read         size,
       *     read               ,
       *           ,         
       */
      read: (data) => {
         
        console.log(data);
      }
    })
    
    const writeStream = new Writable({
         
      write: (chunk, encoding, next) => {
         
        console.log(chunk.toString());
        next()
      }
    })
    
    readStream.pipe(writeStream)
    /**
     *    this.push         ,          ,               
     * push             Buffer,     
     * push          encoding,               encoding
     */
    readStream.push('hello')
    readStream.push('node')
    
    
    一般的なフロー操作
    ストリームからデータを読み出す
    const {
          createReadStream } = require('fs')
    const {
          resolve } = require('path')
    
    readStream = createReadStream(resolve(__dirname, 'home.html'))
    
    let data = ''
    readStream.on('data', (chunk) => {
         
      data += chunk
      console.log('chunk:', chunk);
    })
    
    //       
    readStream.on('end', () => {
         
      console.log("data:", data);
    })
    
    readStream.on('error', (err) => {
         
      console.log(err);
    })
    
    //     
    // chunk: 
    // data: 
    // 
    // 
    //   
    //   
    //   Home
    // 
    // 
    //   

    This is Home Page

    // //
    書込みフロー
    const {
          createWriteStream } = require('fs')
    const writeStream = createWriteStream('out.txt')
    let data = 'hello stream'
    //    utf8       
    writeStream.write(data, 'utf-8')
    //       
    writeStream.end()
    
    //     
    writeStream.on('finish', () => {
         
      console.log('    !');
    })
    writeStream.on('error', (err) => {
         
      console.log(err);
    })
    
    パイプ?フロー
    パイプは入力ストリームへの出力流の機構を提供する.一般的に、1つのストリームからデータを取得し、他のストリームにデータを転送するために使用される.
    const {
          createReadStream, createWriteStream } = require('fs')
    const {
          resolve }= require('path')
    
    const readStream = createReadStream(resolve(__dirname, '   .txt'))
    const writeStream = createWriteStream(resolve(__dirname, 'output.txt'))
    
    //       
    //    input.txt     ,        output.txt    
    readStream.pipe(writeStream)
    console.log('  ');
    
    連鎖流
    チェーンは、出力を別のストリームに接続し、複数のストリーム動作チェーンを作成する仕組みです.チェーンストリームは一般にパイプ操作に用いられる.
    const {
          createReadStream, createWriteStream } = require('fs')
    const {
          resolve } = require('path')
    const {
          Gzip, Gunzip } = require('zlib')
    
    createReadStream(resolve(__dirname, './   .txt'))
      .pipe(Gzip())
      .pipe(createWriteStream(resolve(__dirname, '   .txt.gz')))