reactive-web: Lift をシンプルに

低レベル API

はじめに

ほとんどの場合、reactive-web の内部のことを気にする必要はありません。ただし、複雑な状況の把握が必要な場合には、舞台裏で何が行われているのか理解しておくと役立つかもしれません。とは言え、ここで説明する内容は、ライブラリの典型的な使用法を示すことを意図したものではないことを断っておきます。

reactive-web の中心部奥深くにあるのは、Lift の優れた Ajax および Comet サポートをシンプルに抽象化するしかけです。このしかけにより、javascript を実行するための動的な (スレッドローカルな) スコープを指定することができるようになっています。一部のスコープは comet アクターに javascript を送信することによって javascript を実行するのに対し、別のスコープは javascript を ajax のレスポンスや、ページの最初のレンダリングの一部として出力します。これらのスコープの内部では、reactive-web を使うことで、ブラウザで実行する javascript をキューに入れることができます。このとき、コードがどのスコープに属しているかや、javascript がどのような方法でブラウザに送られるのかについて考慮する必要はありません。

reactive-web はこうしたしかけの上に構築されており、reactive-core に用意されている各種 FRP 機能に加えて、独自の JsEventStream を利用することで、高度な対話性を持つ動的なブラウザコンテンツをレンダリングするための簡潔で合成可能な抽象化機能を提供しています。

もう少し具体的に言うと、キューに入れられた javascript を収集するデフォルトスコープは DefaultScope と呼ばれ、すべての javascript を S.appendJs に渡し、この S.appendJs が、javascript を現在のページにレンダリングしたり、ajax や comet のリクエストの一部としてレンダリングすることを可能にしています。

reactive-web の ajax 呼び出しがやってくると、この呼び出しは LocalScope 内で処理され、キューに入れられた javascript はこの LocalScope が保存します。ついで、Reactive-web の ajax ハンドラがこの javascript を ajax レスポンスとしてブラウザに返します。

一般に、reactive-web のオブジェクトでは暗黙の Page オブジェクトが必要で、この Page オブジェクトがページを一意に識別します。これは何のためかというと、オブジェクトが更新内容を Reactions.inAnyScope ブロック内にラップできるようにし、オブジェクトが ajax リクエストの外部で呼び出されたとき (およびページがレンダリングされた後) でも comet 経由でオブジェクトが動作するようにするためです。その動作のしくみですが、RequestVar[Page] があって、これがページごとに最大 1 度新しい Page を生成していて (ページレンダリング、および Lift がこれに関連付けている ajax 呼び出しをカウントしています)、その値が暗黙的に利用可能になっています。たとえば、PropertyVar をレンダリングするとき、Page への (弱い) 参照が保存されます。この PropertyVar があとで変更された場合、reactive-web は適切な javascript を生成し、これをキューに入れます。もしこれが、その Page に関連付けられている ajax リクエストの最中に起こった場合には、リクエストが完了したときに、該当する javascript がそのレスポンスに含まれます。一方、PropertyVar が、サーバー上またはほかのページで発生したイベントに応答する形で更新された場合には、該当する javascript はページの comet アクターに送信されます。