とりあえず、分かったことだけ。
正しいことを書いてるとは限らないよ!! むしろ昨日はじめて stream2 に触ったからツッコミ待ちだよ!! ドキュメントもサンプルコードも少なくて困ってるよ!! 助けて!!
3つのモード
readable stream には stringMode と objectMode、それと名前はついてないけどいわゆる bufferMode がある。で、stringMode と bufferMode はほぼ同一なのでいいとして、問題は objectMode。
ReadableStream#read([size])の挙動
read() は引数 size が省略された場合、キューの全てを返すことが期待される*1。
しかし、objectMode の場合、キューの中から1つだけ返されるだけである。引数なしの read() を一度呼べば全てのデータが吸い出せるという前提でコードを書くとこの仕様にぶち殺される気がする。返り値が null になるまで読めという指摘もあるかもしれないが、キューに null を突っ込むこともできる。あちゃー。
個人的には、read(2) とかで [{obj: 1}, {obj: 2}] みたいになってほしい。つまり、キューから size ぶんだけ配列で返してほしい。そうすれば read() のときにも [{obj: 1}, {obj: 2}, {obj: 3}] になるし、中身に null が入っていても [null, {obj: 1}] となるから区別できる。
この意見の妥当性をもう一度自分で確かめられたら本家にアイデア投げてみようかなーと思う。
追記1
ReadableStream のことしか考えてなかった。pipe するときに WritableStream#write に配列が投げられたらアレゲだった。でも、結合不可なデータをストリームに流すのってどうかと思うから、オブジェクトを write するときは write([obj]) にしろ、っていうのも悪くないんじゃないかと思った。そうすれば複数チャンクを一度に書き込めるし。
まだまだ考えてみようと思う。
追記2
Twitter 上で id:Jxck さんにいろいろ指摘をいただきました。現状の Stream2 に対する理解が深まりました。ありがとうございます!
ログをだらだら貼り付けておくので、まとめだけ読みたい人は下へどうぞ。
実際、特に違和感は無いなぁ。chunk としてオブジェクトが一つづつ返ってくることが保証されていれば、むしろその方がいいくらいな気も。
@Jxck_ そうすると、object として null を突っ込んだ時の挙動が……
2013-02-11 13:17:28 via YoruFukurou to @Jxck_
@KOBA789 あれ? null の時って objectMode になる?URL
2013-02-11 13:18:47 via Echofon to @KOBA789
@Jxck_ いや、一度 objectMode になったあとで、データとして null が来るとアウトだなー、と。null なんて使うな、という意見も一理ありますが。
2013-02-11 13:19:39 via YoruFukurou to @Jxck_
@KOBA789 データとしての null は object chunk では無いと考えると、それもそれで妥当な気もするなぁ。だって chunk に対して処理できることが無いのは変わらないんだし。
2013-02-11 13:21:19 via Echofon to @KOBA789
@Jxck_ なるほど。そうすると引数なしの read がキューの全てを返すという仕様を覆すのが手っ取り早いことになりますかね?
2013-02-11 13:22:20 via YoruFukurou to @Jxck_
@KOBA789 例えば read() でキューを全ぶ返すのを覆すとして、 buffer の場合何を返せば妥当かな?
2013-02-11 13:25:29 via Echofon to @KOBA789
@Jxck_ あー、なるほど。段々わかってきました。非 objectMode なら結合されてどこまでも 1 chunk である、みたいな考え方ですかね。
2013-02-11 13:26:41 via YoruFukurou to @Jxck_
@KOBA789 そう。つまり、 read() で全部返すのを覆すなら、同時に 「buffer における chunk とは n byte である」という defaultChunkSize が必要になると思う。そのサイズはどう決めるんだって話になるかなぁ。
2013-02-11 13:29:13 via Echofon to @KOBA789
@Jxck_ 現状の stream2 に対する考え方については理解出来ました。ありがとうございます。ただ、理解した上で、個人的にまだその仕様に反論みたいなものがあるので、再度ブログにまとめようと思います。
2013-02-11 13:36:52 via YoruFukurou to @Jxck_
@KOBA789 まあ、俺も探り探りだけど、コメント読むとそんな感じなのかなと。それ以外、やりたいことは _read() の override でやれという感じもするかも。ともあれ俺も参考になりました。 blog 期待 !
2013-02-11 13:38:53 via Echofon to @KOBA789
以下、自分の勝手な解釈。必然的に間違いを含むはず。(てか正解があるなら今すぐ欲しい感)
「書き込む」というとややこしいので、ReadableStream のキューにデータを追加することを「キューに吸い込む」と呼ぶことにする(便宜上)。
まず、ReadableStream には大きく2つのモードがある。それが、objectMode と非 objectMode。キューにデータを吸い込む際、そのデータが string, buffer, null, undefined のいずれでもない場合、自動的に objectMode になる。一度 objectMode になると二度と非 objectMode にはならない。ストリームは object に「汚染」される。
……と、ここまで書きかけて、chunk と呼んでいたものは buffer で、chunk と buffer には区別があるらしいことがわかってしまったので、もう一度まとめ直したい。
あと、コミットログ追っかけてわかったこともあるので、全部まとめ直します、はい……
追記3
リンク張ってなかったけど、続き書きました→ 続: Stream2のモヤモヤ - Write and Run