
シェア:
ケリー・J・アンドリュースはネクスモの開発者支持者であり、5歳で初めてBASICを使い、30年以上コンピュータをいじってきた。
1997年に初めてウェブページを作り、初めてJavaScriptを試してみて初めて、彼は真の天職を見つけた。ケリーは今、JavaScript、テスト可能なコード、そして迅速なデリバリーのために戦っている。
カラオケを歌ったり、マジックを披露したり、カブスやファイティング・アイリッシュを応援したり。
VonageビデオでXStateを学び、適用する
所要時間:7 分
ここ数カ月、ステートマシンについて耳にする機会が増えた。 ステートマシンについてよく耳にするようになった。ステートマシンの考え方は、有限の状態しか持たず、常に1つの状態にしかなれないというものだ。概念的に、これはアプリ開発にとって完璧に理にかなっている。
ステートマシンやステートチャートの概念は新しいものではないし、フロントエンド開発に根ざしたものでもない。これは数学的なモデルであり、私たちの身の回りにある多くのものに使われている。例として、ライトは OFFまたは ON.これは単純な例だが、ステートマシンを使えば何でも記述できる。
On and off states of lightbulb
XState入門
フロントエンド開発におけるステートマシンの使用は、パッケージ XState.XStateは、ステートマシンを定義し、イベントとエフェクトを作成し、アプリケーションフロー全体を制御するのに役立ちます。XStateはJavaScriptのメソッドとオブジェクトを使ってステートマシンを記述します。
上記の電球の例は、次のように書き出される:
const lightBulb = Machine({
id: 'lightBulb',
initial: 'off',
states: {
off: {
on: {
TURN_ON: 'on'
}
},
on: {
on: {
TURN_OFF: 'off',
}
}
}
});ここで定義されたステートマシンは、電球の2つの状態を示している、 OFFと ONおよびイベント TURN_ONと TURN_OFF.
オブジェクトそのものを読むのはそれほど複雑ではないが、ステートマシンが複雑になると理解するのが難しくなる。XStateは、これを支援するツールを作成した。 XStateビジュアライザー.
XStateビジュアライザーを使うと、ステートマシンがどのように動作するかがわかり、インタラクティブなので、遊んでいて楽しい。マシンのコードをチェックしたい場合は、コードボタンをクリックして覗いてみることもできます。
Vonageビデオ状態図の作成
ステートマシンとXStateを学ぼうとしたとき、私の全体的な目標は、Google Meetのようなアプリケーションを作ることだった。 Vonageビデオ.このアプリは、ユーザーが会議室を作成し、URLを共有し、複数のストリームで会議を行うことを可能にする。それを実現するために、ステート・チャートのさまざまな概念と、それをXStateで表現する方法を学ぶ必要があった。
可能性のあるアプリケーションの状態を考え抜くことは、簡単な作業ではないことがわかった。探求すべき多くの可能性があり、最終的に正しい解決策を見つけるには試行錯誤が必要だ。
この記事の残りの部分では、いくつかの基本的な概念を取り上げ、最終的なステートマシンを模倣したステート・チャートの視覚化を構築する。また、各自で調べられるように、追加のリンクやリソースも紹介する。
ステートとステート・ノード
A 状態は、任意の時点におけるマシンの表現である。この瞬間を定義し、それを ステート・ノード構成としてキャプチャされます。
私のVonage Videoアプリでは、これに対していくつかの異なる解決策が考えられますが、できるだけ簡単な言葉で状態を説明することが、有用な結果を得るための最良の方法であることがわかりました。
マシンの作成 マシンは以下のパターンを使用する:
const machine = Machine(state_nodes, options)Videoステートマシンを念頭に置くと、次の2つの複合状態がある。 connectedと disconnected.
2つのステート・ノードは単純化されすぎているように見えるかもしれないが、試行錯誤の結果、ステートは2つしかない。しかし、これらの各状態は、アトミック(子なし)ノードよりも複雑である。XStateは、可能なすべての状態をトップレベルで作成する代わりに、階層的かつ並列的な状態ノードで整理する手助けをしてくれる。
階層的状態ノード
XStateでは、ネストされた状態を作成するオプションが用意されている。 hierarchicalステート・ノード.マシンを最初に起動するとき、これを idleに設定することができる。なぜ別のトップレベルのアトミック・ステート・ノードを作らないのか?
最上位レベルに状態を追加することは「状態爆発」と呼ばれ、有限状態マシンの典型的な副作用である。Vonage Videoはまだ技術的には disconnectedネスト idleは理にかなっている。別の disconnectedサブステートは ready.であるべきだ。 disconnected.ready状態に移行する直前に connected状態に移る直前に起こる。ステートマシンはまた、ステートノードの間に idleと readyですべてをセットアップする。この中間の状態を initフェーズと呼ぶことができる。
ステートマシンは次のようになる:
現在、2つのノードの間を移動する方法がないことにお気づきでしょう。イベントとアクションについては後ほど説明する。
パラレル・ステート・ノード
A parallelステート・ノードは、アプリケーションがすべてのサブステートに同時に存在できるようにします。Vonage Video のステートマシンはイベント駆動型であるため、一度に複数の状態を管理する必要があります。
ステート・ノードがパラレルであることを指定するには、コンフィギュレーションで type:parallelを使う。への遷移後、3つの並列状態が発生する。 connectedへの遷移後、3つの並列状態が発生する。 session, publisherと subscribers.これらの各状態は、Vonage Videoサービスの応答を制御するためのイベントとイベントリスナーを設定します。
出来上がったビジュアライゼーションは次のようになる:
これらのプライマリー・ステートがあれば、特定の時間にアプリケーションが何を表示するかをコントロールできる。しかし現状では、ステート間を移動することはできない。イベントとトランジションを見てみよう。
イベントとトランジション
ステート・ノードは個々のステートのコンフィギュレーションに過ぎないので、ステート・ノードでそれを宣言しなければ、ステートからステートへ移動することはできない。
各ノードは イベントに 次の状態にを待つ。電球の例では TURN_ONに遷移するようマシンに指示する。 on.
遷移は最上位ノード間および階層ノード内でのみ発生する。並列ノード間でトランジションすることはできません。Vonage Videoアプリでは、次のようになります:
ページの準備ができたら
STARTイベントを送ります。このイベントは状態をdisconnected.init.この
disconnected.initステートはVIDEO_ELEMENT_CREATEDイベントが発生すると、状態は遷移します。に到達したら
disconnected.readyに到達したら、ユーザーに接続を許可してCONNECTイベントを送信しconnected.アプリケーションが
DISCONNECTイベントを渡すと、ステートマシンは切断される。
XStateでイベントとトランジションを宣言するには、以下のパターンを使用する:
on: {
EVENT_DESCRIPTOR: 'nextState'
}トランジションに特定のアクションを追加することもできる。トランジションに特定のアクションを追加することもできます。 内部トランジションと外部トランジションのセクションを読むことをお勧めします。様々なタイプのトランジションが詳細に説明されています。
ガードされたトランジション
トランジションのひとつに condノードがあることにお気づきだろう。この条件は guardedトランジション.ガードされたトランジションは、ある条件に基づいて許されない状態に移行しないようにマシンを保護するのに役立つ。この場合、トークンと video 要素の両方が作成されるまで readyに遷移させたくない。
on: {
'VIDEO_ELEMENT_CREATED': {
target: 'ready',
cond: 'checkToken'
}
}ガード条件 checkTokenは、machine に送られる options パラメータにある guards オブジェクトへの名前付き参照である:
const video = Machine(
state_nodes,{
guards: {
checkToken: () => true
}
});
コンテクスト
アプリケーションにとってより便利なものにするために、ステートマシンは extended stateまたは context.コンテキスト・オブジェクトは assign()メソッド.
アクションといえば、今すぐこれらに取り掛かり、残りの骨格を仕上げよう。
行動とサービス
ステートマシンには「副作用」と呼ばれるものがあり、XStateはそれを2つのカテゴリーに分類している:
「Fire-and-forget" - エフェクトがイベントを送信しない。
起動 - イベントを送信する必要がある場合
行動
アクションアクションは単一のエフェクトで、Videoステートマシンでよく使われるエフェクトの1つです。アクションは、ノードに入るときやノードから出るとき、またはトランジション中に使用できます。アクションの順序を理解することは、非常に重要です。
アクションの順番(そしてXStateのすべてのトピック)を学ぶための優れたリソースは、以下のVideoです。 で公開されたビデオだ。が公開したビデオだ。 Egghead.io.アクションがどのように発火するかを理解するのに役立った。
このマシンのアクションの大部分は、トランジションとしてコンテキストの更新を中心に展開される。イベントが呼び出されたら、アクションを使って assign()メソッドを実行する:
on: {
'SOME_EVENT': {
actions: assign({'someContext': (ctx, e) => e.someValue})
}
}
サービス
呼び出されたサービスは、Videoステートマシンにおけるもうひとつの主要なエフェクトである。プロミスやイベントリスナーを使うには、サービスを呼び出す必要がある。この概念を理解するのが一番難しかった。最大の難関は、ステートが終了したときに、呼び出されたサービスが停止することを理解することだった。遷移が早すぎると、プロミスやコールバックが消えてしまう。
Videoステートマシンで使っている主なサービスは、プロミスとコールバックの2つだ。このうち invoke promisesサービスは、ステートマシンがプロミスを使用して解決または拒否し、それに応じて動作することを可能にする。私はこれを、非同期でサーバーとやりとりし、完了したらコンテキストを更新するために使った。
呼び出された約束の関数シグネチャは次のようになる:
src: (context, event) => new Promise((resolve, reject) => {
if (event.error) reject('Rejected')
resolve('Resolved')
}),
onDone: {/*success transition*/}
onError: {/*error transition*/}
このマシンの2つ目の、そしておそらく最も重要な部分は、.......... invoked callbacks.Video アーキテクチャは、イベントとイベントリスナーに大きく依存している。ステートマシンでは、これらはコールバックによって設定されます。例をお見せしましょう:
invoke: {
id: 'initPublisher',
src: (ctx) => (cb) => {
let publisher = initPublisher(pubOptions);
publisher.on('videoElementCreated', (e) => {
cb({ type: 'VIDEO_ELEMENT_CREATED', publisher: publisher })
})
return () => publisher.off('videoElementCreated');
}
}
呼び出されたコールバックの関数シグネチャは以下のようになる:
src: (context, event) => (callback, onReceive) => {
callback('EVENT');
onReceive(event) => { callback('OTHER_EVENT') };
return () => cleanup()
};
アクションとサービスを使用すると、Vonage Videoのステートマシンは次のようになります:
をクリックするのをお忘れなく。 codeタブをクリックして、コンフィギュレーションとしてステートマシンがどのように見えるかを確認してください。
リソースとまとめ
よし、ここまで来た。
I'm proud of you!
XStateを見るのが初めてなら、一度にすべてを理解するのは大変なことだ。私はまだ模索中で、新しいやり方を学んでいる。この記事は、世の中にあるもののほんの一部です。あなたが学んでいる間、チェックしたい素晴らしいリソースをいくつか紹介します。
XStateについて質問があれば、お気軽にご連絡ください!