メモを揉め

お勉強の覚書。

RxJSのOvservableを可視化しながら編集できるエディタを作りました

これは何?

all-user.github.io

RxJSのObservableを返すコードを書くとそのストリームに流れてくるイベントがリアルタイムに可視化されるエディタです。

下は実際に触っているところをスクリーンキャストにしたところです。
ダブルクリックの判定を書いています。

RxJSのObservableを直感的に扱えるように

以前このブログで書いた非同期処理の記事の中では次のように紹介しました。

値が次々に流れてくる川の流れのような時間軸を、そのまま抽象化したオブジェクトと言えるかもしれません。 RxJSを使うと、その川の流れのようなオブジェクト同士を、つなげたり、束ねたり、分岐したり、フィルターしたりできます。

イメージで伝われ!図解JavaScriptの非同期処理 - メモを揉め

この川のことをイメージする時にマーブルダイアグラムを見たり、プリントデバッグしたりしていたのですが、もっと直感的な方法は無いものかと考えていました。
そんな中、Observableについて記事に書いた際、この概念を文章で伝えるのめちゃくちゃ難しいな、いい感じにビジュアライズできないかなと思いたって作り始めたのがこのエディタです。

使い方

Observableを編集する

画面上部から順に並んでいる水平線がRxJS Observableのイベントが流れてくる川を表したものです(以下ストリームと呼びます)。
ストリームは水平線と対となる編集可能なコード部分を持ち、ここにObservalbeを返すJSの式を書くと、その式を評価した結果のObservableが左側に表示されている_0$という変数に代入されます。
この_0$という変数は、各ストリーム毎に_0$,_1$,_2$..._N$という風に、上から順にインクリメントされた数字を含む名前が割り当てられ、自身より後方のコードで自由に参照することができます。
(非同期に参照すれば後方の変数もたぶん参照可能です)

エディタ内で使用できるオペレーターとメソッド

RxJS 6のすべてのオペレーターとメソッドを使用できます。
ただし、コードは以下のようにwithを使用して実行されているため、同名の場合はメソッドが優先されます。

import * as rxjs from 'rxjs';
import * as operators from 'rxjs/operators';

with (Object.assign({}, operators, rxjs)) {
  /* ... */
}

イベントの中身を見る

各イベントをクリックすると、画面下部にイベントの値をJSON.stringifyしたものが表示されます。
イベントは型の種類によって表示が変わります。

type 表示
string f:id:alluser:20190930210047p:plain
number f:id:alluser:20190930210219p:plain
boolean f:id:alluser:20190930210408p:plain f:id:alluser:20190930210442p:plain
null | undefined f:id:alluser:20190930210708p:plain
それ以外 f:id:alluser:20190930210801p:plain

ストリームを追加する

一番下にあるストリームのすぐ下の+と書かれた丸いボタンをクリックすると一番下に新しいストリームが追加されます。

ストリームを削除する

一番下のストリームの右の赤い文字で×と書かれたボタンをクリックすると一番下のストリームを削除することができます。

エラーの中身を見る

ストリームエディタに書かれた内容を評価した際にエラーが発生すると、画面下部のスペースにエラーメッセージが表示されます。

TODO

これから実装したいと思っているけどまだ手をつけられていない機能たちです。

  • 保存
    • local storageに保存
    • インポート・エクスポート
  • プリセット
  • 色分け
  • ストリームの順序入れ替え

少しづつ手をつけていければと思います。

実装について

Vue + Vuex + TypeScriptで実装しています。
RxJSはと言うともちろん使ってるのですが、今のところストリームそのものにしか使えていません。
もっと複雑になってきたら考えたいと思います。

環境構築はvue-cliで行いました。
LinterとしてTSLintかESLintが選べるのですが、ESLintを選ぶとエラーが出て動かなかったのでTSLintにしました。タイミング的にESLintが6にメジャーバージョンアップしたタイミングだったと思うので、その辺りの関係でうまくいかなかったような気がします。
なんだかんだまだESLintに寄せた設定をまだ試せていないのでどこかで乗り換えたいです。

コンポーネントはvuex-property-decoratorを使ってクラススタイルで。 Vuexの型付けはvuex-smart-moduleを使うことで実現しています。
これはほんとにおすすめで、これまで自前の型定義で頑張ったりもしてきましたが、現時点のVuex + TypeScriptのベストプラクティスはこれじゃないかなと思っています。

github.com

ぜひさわってみてください

フィードバックなんかいただけると励みになります。
RxJSを使う時は普通に結構便利だと思うので、今後も使っていくと思います。

rxjs-stream-editor