>  기사  >  웹 프론트엔드  >  Nodejs의 이중 스트림에 대한 간략한 토론

Nodejs의 이중 스트림에 대한 간략한 토론

青灯夜游
青灯夜游앞으로
2020-11-23 17:52:343998검색

Nodejs의 이중 스트림에 대한 간략한 토론

관련 추천: "node js tutorial"

듀플렉스 스트림은 읽기 및 쓰기 가능을 동시에 구현하는 스트림으로 업스트림 생산 데이터와 다운스트림 소비 데이터로 사용할 수 있으므로 데이터에 포함될 수 있습니다. flow 파이프라인 중간 부분, 즉

 rs.pipe(rws1).pipe(rws2).pipe(rws3).pipe(ws);

NodeJS

  • Duplex

  • Transform

Duplex

구현 Duplex

에는 두 가지 일반적으로 사용되는 이중 스트림이 있습니다.

읽기 가능, 쓰기 가능 구현 방법 마찬가지로 Duplex 스트림 구현은 매우 간단하지만 Duplex는 Readable과 Writable을 모두 구현합니다. NodeJS는 다중 상속을 지원하지 않으므로 Duplex 클래스를 상속해야 합니다

  • Duplex 클래스 상속

  • _read() 메서드를 구현합니다.

  • _write() 메소드 구현

read() 및 write() 메소드 구현은 모두가 읽기 및 쓰기 가능과 동일하기 때문에 익숙하다고 생각합니다.

const Duplex = require('stream').Duplex;

const myDuplex = new Duplex({
  read(size) {
    // ...
  },
  write(chunk, encoding, callback) {
    // ...
  }
});

생성자 매개변수

Duplex 인스턴스에는 읽기 가능하고 쓰기 가능한 스트림이 모두 포함되어 있습니다. Duplex 클래스를 인스턴스화할 때 여러 매개변수를 전달할 수 있습니다.

  • readableObjectMode: 읽기 가능한 스트림이 ObjectMode로 설정되어 있는지 여부, 기본값은 false
  • writableObjectMode: 쓰기 가능한 스트림이 ObjectMode로 설정되었는지 여부, 기본값은 false
  • allowHalfOpen: 기본값은 true입니다. false로 설정하면 쓰기 끝이 끝나면 스트림이 자동으로 읽기 끝을 종료하고 그 반대의 경우도 마찬가지입니다. 물론.

작은 예제

Readable과 Writable을 이해한 후 Duplex를 보면 매우 간단합니다. 공식 홈페이지에 있는 예제를 사용하면 됩니다

 const Duplex = require('stream').Duplex;
const kSource = Symbol('source');

class MyDuplex extends Duplex {
  constructor(source, options) {
    super(options);
    this[kSource] = source;
  }

  _write(chunk, encoding, callback) {
    // The underlying source only deals with strings
    if (Buffer.isBuffer(chunk))
      chunk = chunk.toString();
    this[kSource].writeSomeData(chunk);
    callback();
  }

  _read(size) {
    this[kSource].fetchSomeData(size, (data, encoding) => {
      this.push(Buffer.from(data, encoding));
    });
  }
}

물론 실행할 수 없는 의사 코드이지만, Duplex의 역할을 볼 수 있고, 데이터를 생산할 수도 있고, 데이터를 소비할 수도 있으므로 데이터 흐름 파이프라인의 중간에 있을 수 있습니다. Transform

    Transform도 이중 스트림이며 Duplex처럼 보입니다. 반복되지만 둘 사이에는 중요한 차이점이 있습니다. Duplex에는 읽기 가능하고 쓰기 가능한 스트림이 있지만 상대적으로 독립적인 Transform의 읽기 가능한 스트림에 있는 데이터가 자동으로 입력됩니다. 특정 프로세스 이후의 쓰기 가능한 스트림.
  • 읽을 수 있는 스트림에서 쓰기 가능한 스트림으로 바뀌더라도 둘 사이의 데이터 양이 동일하다는 의미는 아닙니다. 위에서 언급한 특정 처리 로직에 따라 읽기 가능한 스트림을 변환한 후 데이터에 넣을지 여부가 결정됩니다. 쓰기 가능한 스트림 변환 원래 의미 변환 흐름 기능을 매우 적절하게 설명하는 변환입니다.
  • 압축 및 압축 해제를 위한 가장 일반적인 zlib는 변환 스트림입니다. 압축 및 압축 해제 전과 후의 데이터 양은 분명히 다릅니다. zlib의 기능은 zip 패키지와 압축 해제된 파일을 입력하거나 그 반대로 하는 것입니다. 우리가 일반적으로 사용하는 대부분의 이중 스트림은 변환입니다.
Tranform 구현

Transform 클래스는 내부적으로 Duplex를 상속하고 writable.write() 및 readable._read() 메서드를 구현합니다. Transform 스트림을 사용자 정의하려면

Transform 클래스만 상속하면 됩니다.

_transform() 메서드 구현

    _flush() 메서드 구현(선택 사항)
  • _transform(chunk, 인코딩, 콜백) 메서드는 데이터를 수신하고 출력을 생성하는 데 사용됩니다. Writable과 마찬가지로 decodeStrings가 false로 설정되지 않은 한 청크의 기본값은 Buffer입니다.
  • _transform() 메서드 내에서 this.push(data)를 호출하여 데이터를 생성하고 쓰기 가능한 스트림에 넘겨주거나 호출할 수 없습니다. 즉, 입력이 출력을 생성하지 않음을 의미합니다.

  • Callback(err, data)은 데이터 처리 시 호출되어야 합니다. 첫 번째 매개변수는 오류 정보를 전달하는 데 사용됩니다. 두 번째 매개변수를 전달하는 경우 효과는 this.push( data)
  •  transform.prototype._transform = function (data, encoding, callback) {
      this.push(data);
      callback();
    };
    
    transform.prototype._transform = function (data, encoding, callback) {
      callback(null, data);
    };

    때로는 변환 작업에서 스트림 끝의 쓰기 가능한 스트림에 더 많은 데이터를 써야 할 수도 있습니다. 예를 들어 Zlib 스트림은 압축된 출력을 최적화하기 위해 일부 내부 상태를 저장합니다. 이 경우, 작성된 모든 데이터가 소비되기 전에 호출되어 '종료'를 트리거하는 _flush() 메서드를 사용할 수 있습니다.

  • Transform 이벤트

Transform 스트림에는 일반적으로 사용되는 두 가지 이벤트가 있습니다.

finish from Writable

end from Readable

    transform.end()가 호출되고 데이터가 _transform()에 의해 처리되면 완료됩니다. 나중에 트리거됩니다. _flush를 호출한 후 모든 데이터가 출력되고 종료 이벤트가 트리거됩니다.
  • 비교

  • 읽기 가능 및 쓰기 가능을 이해하면 이중 스트림을 이해하는 것이 매우 자연스럽습니다. 그러나 이 둘의 차이점은 일부 초보자에게 혼란을 줄 수 있습니다. 간단한 차이점은 Duplex의 읽기 가능 스트림과 쓰기 가능 스트림 사이에는 직접적인 관계가 없다는 것입니다. Transform의 읽기 가능한 스트림에 있는 데이터는 처리 후 쓰기 가능한 스트림에 자동으로 저장됩니다.
  • 두 가지 간단한 예를 보면 Duplex와 Transform의 차이점을 직관적으로 이해할 수 있습니다

TCP 소켓

net 模块可以用来创建 socket,socket 在 NodeJS 中是一个典型的 Duplex,看一个 TCP 客户端的例子

var net = require('net');

//创建客户端
var client = net.connect({port: 1234}, function() {
    console.log('已连接到服务器');
    client.write('Hi!');
});

//data事件监听。收到数据后,断开连接
client.on('data', function(data) {
    console.log(data.toString());
    client.end();
});

//end事件监听,断开连接时会被触发
client.on('end', function() {
    console.log('已与服务器断开连接');
});

可以看到 client 就是一个 Duplex,可写流用于向服务器发送消息,可读流用于接受服务器消息,两个流内的数据并没有直接的关系。

gulp

gulp 非常擅长处理代码本地构建流程,看一段官网的示例代码

gulp.src('client/templates/*.jade')
  .pipe(jade())
  .pipe(minify())
  .pipe(gulp.dest('build/minified_templates'));

其中 jada() 和 minify() 就是典型的 Transform,处理流程大概是

.jade 模板文件 -> jada() -> html 文件 -> minify -> 压缩后的 html

可以看出来,jade() 和 minify() 都是对输入数据做了些特殊处理,然后交给了输出数据。

这样简单的对比就能看出 Duplex 和 Transform 的区别,在平时实用的时候,当一个流同事面向生产者和消费者服务的时候我们会选择 Duplex,当只是对数据做一些转换工作的时候我们便会选择使用 Tranform。

更多编程相关知识,请访问:编程学习网站!!

위 내용은 Nodejs의 이중 스트림에 대한 간략한 토론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제