2016-10-04 WHATWG Streams の覚書 (2)
2016-10-03 も書いたが bouzuya/whatwg-streams-example で whatwg/streams の参考実装を試している。進捗はほとんどない。src/
から test/
に code を移しているくらいだ。
WHATWG Streams のことを分かる範囲ですこしだけ書いておく。前提として昨日 (2016-10-03) 書いたとおり Model を読んでいるものとする。
WHATWG Streams は 3 つの Stream class が登場する。
ReadableStream
WritableStream
TransformStream
ReadableStream
は underlying source の wrapper だ。underlying source から enqueue()
された chunk を internal queue に持つ。consumer はそれを読み取る。high-level な操作としては pipeTo()
で WritableStream
に pipe できたり、pipeThrough()
で TransformStream
に pipe できる。ほかに tee()
で分岐できる、これはまたあとで触れる。low-level な操作としては getReader()
で read()
できる。high-level な操作も内部では getReader()
を使う。
ReadableStream
もっとも重要な点は reader をひとつしか持てない (lock) 点だ。ReadableStream
は getReader()
を呼び出すと reader が得られる。この reader が lock を開放するまで、ReadableStream
は getReader()
を呼び出せない。pipeThrough()
/ pipeTo()
/ tee()
はすべて getReader()
を使用するので同様だ。RxJS Observable や Node.js Stream との一番の違いはここだと思う。
ちなみに tee()
の場合は、その ReadableStream
を lock する代わりに新たな ReadableStream
をふたつ返す。それらを getReader()
すれば複数での読み取りは困らないだろう。
WritableStream
は underlying sink の wrapper だ。producer から writer で write()
された chunk を internal queue に持つ。underlying sink に write()
する。ReadableStream
の対なので難しい点はない。もちろん getWriter()
は low-level な操作だし、 WritableStream
を lock する。
TransformStream
は ReadableStream
と WritableStream
をまとめたものだ。pipeThrough()
に渡す。現状の仕様には何も書かれていない。参考の実装を見た範囲では現状 readable
と writable
property でそれらを返すようになっているだけだ。pipeThrough()
の実装を読むと TransformStream
への要求が分かりやすい。
pipeThrough({ writable, readable }, options) {
this.pipeTo(writable, options);
return readable;
}
ここまでで分かるとおり ReadableStream
/ WritableStream
/ TransformStream
で pipe chain をつくる。主な流れは次のとおりだ。 underlying source -> ReadableStream
-> TransformStream
-> WritableStream
-> underlying sink 。
とりあえず今日はここまで。
覚書: underlying source / underlying sink こそ使うことに触れていない。 API について書いてから触れる。back pressure には触れてない。queuing strategy を調べてから触れる。