Typy.PromiseっていうPromiseの実装を車輪の再発明よろしく作ってみました。npmとbowerにあげてます。なんでこんなの作ったのかというと、作ってみたかったっていうのが一番の理由です。他意はないです。はい。
作るときにできる限り忠実に作りたいなぁと思って、読めない英語を感で適当に斜めに、イメージしながら読んで、ChromeとかFirefoxとかSafariとかを動かしながら作ってます。この間書いたJavaScript Promiseの実行順序(Firefox31とChrome37で違うけどどっちが正しい?)ってのもその副産物です。
で、今日の内容も謎があったのでどないなん?ってところです。ちなみに大いに嘘が書かれてるかもしれないことはあらかじめご承知おきを。
Promise.all/raceの引数はiterable
仕様をみるとPromise.all/raceの引数はどうやらiterableなオブジェクトみたいです。直リンクが貼れなかったのですが、リンク先の25.4.4.1とか25.4.4.3とかに書いてます。iterableってなんすか?ってことで、まぁ、予想的にはfor..ofでくるくる回せるやつかなぁ。ってところなんですが、仕様読んでるとGetIteratorってのがあるので、中見てみます。で、さらに読み進めるとCheckIterableってのがあってどうやらこいつが確信っぽいです。
CheckIterable
CheckIterableをみると、iterableかどうかは以下のように判断しろみたいな感じですかね。
- 値がobjectかどうか判断して、そうでなかったらiterableではない
- @@iteratorプロパティがあったらiterable。そうでなかったら、iterableじゃない。
というらしいです。いやいやいや、@@ieratorってどうやって取るのさ!?
あっ、いけた。。。。いやいやいやいや。いいのか Firefox!?これ内部プロパティじゃないんすか??ちなみにChromeではダメでした。(実装されててダメなのか、実装されてないのかは不明)
@@iteratorはどんなオブジェクトに実装されてるのか
ということで、疑問は次なる段階に進んで、じゃ、@@iteratorってどんなのに実装されてるのよって思ったわけです。MDNでiterableを見てみるとこんな感じ。StringとかArrayとかMapとかSetとかにあるみたいです。Generatorはひとまず置いとくとします。
確かにいけてますね。オブジェクトでもなんか返ってきてるのは、とりあえずは置いときます。
StringがiterableならPromise.all/raceに渡したときにどうなるのか?
やっと本題。StringがiterableならPromise.all("hoge")とかPromise.race("fuga")ってしたときにどういう動きをするのかの疑問が湧きました。仕様をちゃんと読めば書いてあるのかもしれないですが、英語よくわかりません。
直感的には、渡された引数がPromiseで無くって、thenableでもない場合は、Promise.resolveされてPromiseに変換された内容を使いそうな気がするので、Promise.resolve("hoge")みたいな感じなのかなと思うのですが、でもStringはiterableなので、一文字づつPromise.resolveされるようにも思えます。
Promise.all("hoge");
↓
Promise.all([
Promise.resolve("h"),
Promise.resolve("o"),
Promise.resolve("g"),
Promise.resolve("e")
]);
みたいな。で、とりあえずやってみようってことでFirefoxでやってみました。
ある意味で、そらそうか。って感じです。が、Stringはiterableやのになんで動かへんねん。っていう疑問もあります。いや、動かれると非常に気持ち悪いので動いてくれないほうがいいのはいいのですが。
と、いうことでとりあえず怒られます。
続いて、Setやったらどうやろうって思って試してみます。
うん。キーのほうが戻ってきてますね。個人的には値のほうが欲しいのですが。もしくはタブルみたいな感じで両方ともか。ちなみにChromeでは動きません。
結論
よくわからんので、もうちょい調べる。とりあえず、iterator周りからかな。