それでは、Rx for JavaScriptとは何ですか?
RxはReactive Extensionsの略です。 定義がプロジェクトページで述べているように:
Rxは、Observerパターンに従って、コレクションを使用して非同期およびイベント指向のプログラムを作成するためのライブラリです。
主なアイデアは、非同期コンピューティングをデータソースとして考慮することです。 たとえば、コンピューターのマウスは、クリックやカーソルの動きのソースにすぎません。 Observable Collectionsは、このようなデータセットを操作するために使用されます。 RxJSのルーツは.NETの世界にあるため、一部のLINQ機能(select、where、take、skipなど)が利用可能になります。 これについては少し後で説明しますが、今のところは、ライブラリの構造を検討してください。
既存のフレームワークとの統合
開始するには、次のリンクから RxJSをダウンロードしてください 。 jQuery、MooTools、プロトタイプ、Dojo、ExtJS、およびGoogleマップなどの一般的なサービスを操作するための拡張機能が含まれています。 ライブラリ自体は、1つの7.4 kb rx.jsファイル(30 Kバイトの非圧縮)で構成されています。
![](https://habrastorage.org/storage1/6baeb0d8/7810988a/9b39028d/63c43ccb.png)
例では、Web DeveloperパッケージがインストールされたVisual Studio 2010がエディターとして使用されます。 クライアントフレームワークはjQueryです。
したがって、単純なHTMLページを作成し、RxJSをプラグインします。
<head> <title>Samplestitle> <script type="text/javascript" src="Scripts\rx.js"></script> <head>
その後、IntelliSenseはRxメソッドの表示を開始します。
![](https://habrastorage.org/storage1/5e61fa71/3a9986e6/420f8b2d/d0fbd296.png)
理論のビット
先に進む前に、Rxで採用されている用語と規則のいくつかを明確にしたいと思います。
- Observable-コレクション、イベントを生成してサブスクライバーに送信するデータソース。
- オブザーバー(「オブザーバー」)-ソースからの信号を処理するサブスクライバー。
- ObserverイベントをサブスクライブするのはObservableですが、そうでない場合はそうではありません。
- Rxの基礎は、モナドの理論ですが、古典的な形では実現されていません。 それらの存在は、「遅延」(遅延)計算、およびそれらの一部を元に戻す機能で表現されます。 この時点で、この記事の後半でさらに詳しく説明します。
- コールドオブザーバブル-Subscribeメソッドを呼び出した後にのみサブスクライバーに新しいデータを送信するソース。
- ホットオブザーバブルは、サブスクライバーがいない場合でもデータを送信するソースです。 Subscribeを呼び出した後、クライアントは生成の開始時からではなく、現時点からのみデータを受信し始めます。 例は、DOM要素のイベントです。
- RxJSメソッドの名前はCamelCaseルールに従います。
オブザーバー
上記のように、SubscribeメソッドはObservableイベントをサブスクライブするために使用されます。
var source = null; var subscription = source.Subscribe( function (next) { console.log("OnNext: " + next); }, function (exn) { console.log("OnError: " + exn); }, function () { console.log("OnCompleted"); });
そして
var source = Rx.Observable.Empty(); var observer = Rx.Observer.Create( function (data) { $(" ").text(data).appendTo("#content"); }); var handle = source.Subscribe(observer);
Subscribeメソッドの詳細を検討してください。
- 作成/送信されたオブザーバーへの参照(ハンドル)を返します
- 最初のオーバーロードとして、最大3つのパラメーターを受け入れます。データ配列の各要素のハンドラー(OnNext)。 例外ハンドラー(OnError); 完了ハンドラー(OnCompleted)
- 2番目のオーバーロードでは、OnNext、OnError、OnCompletedの各イベントを管理できるように、既に作成されたObserverが転送されます。
![](https://habrastorage.org/storage1/febece32/7f44e9ed/a797eb12/b848ee2d.png)
オブザーバの登録を解除するための個別の方法はありません。 代わりに、Disposeパターンは.NET環境からRxJSに導入されました。
したがって、オブザーバーのリンク(ハンドル)にはDisposeメソッドが含まれており、これを呼び出すことでオブジェクトを破棄できます。
![](https://habrastorage.org/storage1/55c994c1/0ac9a4aa/bdfb8131/434698da.png)
オブザーバブル
ほとんどの場合、Webサービスの呼び出しであろうと、DOM要素を使用する場合であっても、常に「ホット」ブラウザを使用します。 実際のアプリケーションの「コールド」ブラウザはそれほど一般的ではありませんが、ユニットテスト中にその目的が明確になります-事前に準備されたデータセットを操作します。
以下は、Observableとその説明を作成するためのAPIテーブルです。
メソッド名 | 説明 |
空() | OnCompletedを呼び出す空のコレクションを返します |
投げる(error_msg) | OnError呼び出しで空のコレクションを返します |
戻り値(値) | 1つのアイテムのコレクションを返します |
範囲(開始、カウント) | 32ビット整数の配列を返します |
生成(initial_state、condition、selector、iterate) | 次のパラメーターで作成されたコレクションを返します |
GenerateWithTime(時間) | Generateメソッドに似ていますが、要素の生成間に時間間隔を追加します |
なし() | イベントを呼び出さずに空のコレクションを返します |
toObservable(event_name) | jQueryオブジェクトを操作するための拡張機能 |
FromArray() | JS配列からコレクションを初期化します |
作成(subscribe_detail) | オブザーバーサブスクリプションの詳細のコレクションを作成します |
FromDOMEvent(dom_element、event_name) | DOM要素を操作するための拡張機能 |
FromIEEvent(dom_element、event_name) | Internet ExplorerのDOM要素の特定のイベントを操作するための拡張機能 |
FromHtmlEvent(dom_element、event_name) | FromDOMEvent()およびFromIEEvent()の汎用メソッドです |
LINQ
そのため、RxJSの最も興味深い機能の1つであるLINQサポートにアクセスします。 .NETプラットフォームで利用できるこのすばらしい技術について多くの人が聞いたことがあると思います。
LINQはLanguage Integrated Queryの略で、さまざまなコレクションを照会できます。 RxJSの出現により、すべてのメソッドがJavaScriptの世界にもたらされたわけではありませんが、最も有用なものは次のとおりです。
- 選択(SelectMany)
- テイク(TakeUntil、TakeWhile、TakeLast)
- どこで
- スキップ(SkipUntil、SkipWhile、SkipLast)
- Groupby
- 等
新しいものが追加され、ここにのみ表示されます。
- DistinctUntilChanged-コレクションの状態を監視します。 OnNext、OnCompletedイベントは、データが変更されたときにのみ発生します。
- Do-DistinctUntilChangedを呼び出す前に新しいデータへのアクセスを提供します
- スロットル-コレクションが新しいデータを追跡するまでの最小時間を設定します
- タイムスタンプ(RemoveTimestamp)-データ制御をオペレーターに転送する代わりに、タイムスタンプが渡され、処理後に次のステートメントが呼び出されます
完全なリストは提供しません。なぜなら 残りのメソッドは自分で確認できます。
以下の図をより明確に理解するために、イベントのサブスクリプションの図を示します。
![](https://habrastorage.org/storage1/46715c3f/bd0019e7/6daee188/251dc02b.png)
JavaScriptにはラムダ式が存在しないため、LINQメソッドのパラメーターとしての役割は通常の関数によって実行されます。
var items = [1, 2, 3, 4, 5]; var observable = Rx.Observable.FromArray(items).Select(function (item) { return { Value: item, Sqrt: Math.sqrt(item) }; }).Where(function (item) { return item.Value + 2 < 5; });
新しい関数(DistinctUntilChanged、Throttleなど)に戻り、それらの非常に有用な機能に注目したいと思います。 そのため、状況によってはsetIntervalとsetTimeoutを使用してThrottleが置き換えられ、DistinctUntilChangedと組み合わせて使用すると、たとえば、テキスト入力時のajaxリクエストの数が減少します。
そして、例のための視覚的なコード:
var input = $("#textbox").toObservable("keyup") .Select(function (event) { return $(event.target).val(); }) .Timestamp() .Do(function (inp) { var text = "I: " + inp.Timestamp + "-" + inp.Value; $(" ").text(text).appendTo("#content"); }) .RemoveTimestamp() .Throttle(1000) .Timestamp() .Do(function (inp) { var text = "T: " + inp.Timestamp + "-" + inp.Value; $(" ").text(text).appendTo("#content"); }) .RemoveTimestamp() .DistinctUntilChanged(); var subscribtion = input.Subscribe(function (data) { $(" ").text("Your text: " + data).appendTo("#content"); });
したがって、DistinctUntilChangedを呼び出してテキストフィールド値の配列を渡す前に、何らかのログを記録します。
スパゲッティコードにノーと言う!
記事のこの最後の部分では、すでに何度か言及されているWebサービスの操作を検討したいと思います。
このコードについて何回書いていますか:
$.ajax({ url: "your_url", dataType: "json", success: function (data, textStatus, xhr) { $("#results").empty(); $.each(data[1], function (_, result) { $("#results").append(" " + result + " "); }); }, error: function (xhr, textStatus, errorThrown) { $("#error").text(errorThrown); } });
かなり頻繁に思います。 彼の問題は何ですか? そうです、データ処理ロジックはデータソースの定義と共にカプセル化され、「スパゲッティコード」になります。
RxJSはこの問題を解決します。 最初に、jQueryと統合するための拡張機能であるrx.jQueryファイルを含める必要があります。
その後、上記のコードを少しリファクタリングします。
function serviceCall(text) { return $.ajaxAsObservable( { url: "your_url", dataType: "json", format: "json", data: text }); } var source = serviceCall("search me"); var handle = source.Subscribe(function (result) { $("#results").append(" " + result + " "); }, function (exn) { $("#error").text(exn); });
したがって、リクエスト自体からデータ処理ロジックを分離し、リクエスト自体を本質的にラップしました。
あとがき
この記事では、JavaScriptライブラリーのReactive Extensionsの力を示したかったのです。 その適用範囲は非常に広範囲で、プログラマーのニーズによってのみ決定されます。 私自身の経験から言えば、Observable CollectionsとRxJSの哲学自体は、すでに確立されているコード作成プラクティスのレビューを必要としていますが、それだけの価値はあります。
単体テスト、操作のキャンセル、およびSelectMany演算子は考慮されませんでした(モナドが表示される場所です)が、それについては次の記事で詳しく説明します。
PS
いくつかのポイントをより詳細に説明する便利なリンクのリスト:
- JavaScriptのReactive Extensionsの概要-オブザーバブルの作成
- RxJSでのゲーム開発
- linq.js-このライブラリはRxとは関係ありませんが、JavaScriptでLINQが気に入った場合、その90のメソッドは非常に便利です。
- スターター材料