blog.bouzuya.net

2016-02-06 bouzuya/virtual-dom-ssr で promise chain を維持する state container をつくった

bouzuya/virtual-dom-ssr で模索していることと、その過程でつくった promise chain を維持する state container の例を書く。まとまっていない。

現状の bouzuya/virtual-dom-ssr は client / server で処理を共通化できていない。その共通化の方法について検討している。たとえば、昨日 (2016-02-05) の routing で言えば、routing 後の処理やその結果をやりとりする方法に迷っている。やりとりする方法をどうすれば client / server でうまく処理を共通化できるのかで迷っている。

いまの案はすべてを event 化することだ。一例は次の通りだ。

  1. request を event に変換する
  2. event を「 state を更新する関数」に変換する
  3. 変換された「 state を更新する関数」で state を更新する
  4. 更新された state を Virtual DOM に変換する
  5. 変換された Virtual DOM を HTML / DOM として描画する

この処理の流れは cyclejs/todomvc-cyclebouzuya/cycle-gh-tree で採用している。挙げた例はどちらも Cycle.js で実装されたものだ。これらの例では cycle-dom を使って event を RxJS の Observable として受け取る。それらを束ねたり関数に変換して state へ適用する。最後に更新された state を cycle-dom に流すことで描画できる。今回は Cycle.js を使用しないつもりだ。Cycle.js (RxJS) の代わりに EventEmitter を使用して、似たような処理の流れをつくろうとしている。

すべてを event 化する案の問題は request を対応する response に変換しないといけないということだ。この問題は Cycle.js をやめたいと書いた 2016-02-03 に近い。 request から event に変換するのは良いが、きっちりと request に対する response を得ることが難しくなりがちだ。

ひとまず、「 state を更新する関数」と state を扱うための data 構造をつくることにした。 Promise chain を維持する state container だ。

bouzuya/virtual-dom-ssrproperty.ts がそうだ。利用例は次のとおりだ。

const property = new Property({ name: 'bouzuya' });
property.update((state) => {
  return { name: state.name + '!' };
});
property.update((state) => {
  return { name: state.name + '?' };
});
property.value().then((state) => {
  console.log(state.name); // 'bouzuya!?'
});

良い構造になったら npm package として切り出してもいいかもしれない。ただ、これは RxJS で簡単に代替できそうだし、似たような構造を普段からよく見ている気がする。

追記: bouzuya/promised-state として切り出した。

一日 EventEmitter でゴリゴリ書いてみた結果、 DOM driver 以外の使用を避けて、副作用も気にしなければ Cycle.js でいいんじゃないかという気がしてきた。これについてはまたそのうちに書くと思う。