web-dev-qa-db-ja.com

約束を意識したイベントシステムは望ましいですか?

Promisesとeventingはどちらも非同期プログラミングを行う方法であり、特定のプロジェクトに対してどちらかを選択できることを十分に認識しています。ただし、実際には、私が使用しているコードベースは大きく、非同期性を異なる方法で処理する多くのサードパーティライブラリを使用しているため、2つのアプローチを混在させることは避けられません(多くの場合、悲惨な影響があります)。

イベントハンドラーが完全に終了することを期待しながら、人々がイベントを起動し、その後さらに多くのことを行うのを何度も見ました。残念ながら、一部のイベントハンドラーはPromiseのチェーンを開始しますが、イベントソースがそのチェーンがいつ解決されたかを知る方法はありません。

理論的には、純粋なイベントのみで非同期プログラミングを行う適切な方法は、イベントハンドラーが「event_x_completed」イベントを発生させることでしたが、元の「event_x」には常に1つのイベントハンドラーが存在することを前提としています(ただし、醜くなるコード。下部の例を参照してください)。 UIプログラミングでは、リスナーの数を気にする必要はありません。例えば。 1つのユーザーアクションでイベントが発生し、任意の数のUIコンポーネントがトリガーされて更新されます。

また、実行方法によっては、イベントソースとイベントリスナーの間に緊密な結合が生じる可能性があり、そもそもイベントを使用する大きな強みが無効になります。私のプロジェクトには複雑なUIがあるため、イベントソースはイベントをリッスンしているハンドラーの数を気にすることはできません。

各ハンドラーがPromise(またはthen-ableオブジェクト)を返すかどうかをテストするイベントシステムがあれば素晴らしいと思います。fire( "event_x")はPromise.all(all_promises_from_handlers)をイベントソースに返す必要があります。

私は周りを見回しましたが(おそらく十分に難しいことではありません)、Promise対応の総合馬術システムについて話している人は誰もいません。人々は同じ問題を抱えていますか?それはどのように扱われますか?

具体例の編集:

「SAVE_PRESSED」の作成者は、ハンドラーがいくつあるかは気にせず、すべて完了したことだけを気にします。これができると非常に便利だと思います。

function saveClicked() {
    saveButton.disable();
    EventManager.raise("SAVE_PRESSED").then(function() {
        saveButton.enable();
    });
}

純粋なイベントでは、もちろん、すべてのリスナーをループして、代わりにこれを行うことができます。

function saveClicked() {
    saveButton.disable();
    var listeners = EventManager.getListeners("SAVE_PRESSED"); // array
    EventManager.raise("SAVE_PRESSED");
    EventManager.listen("SAVE_COMPLETED", function(listener_id) {
        var index = listeners.indexOf(listener_id);
        listeners = listeners.splice(index, 1);
        if (listeners.length === 0) {
            saveButton.enable();
            // AND -- unregister this function as a handler for SAVE_COMPLETED
        }
    });
}

私がこれについて好きではないこと:

  • コードは長く、完全ではなく、適切なエラー処理がありません。
  • これは、リスナーが「* _COMPLETED」イベントを発生させるかどうかによって異なります。
    • これが常に当てはまるとは限らない場合、各リスナーは、非同期である(COMPLETEDイベントを発生させる)かどうかを示す必要があります。これは、維持する追加の構成です。
    • そして、EventManager.getListeners( "SAVE_PRESSED")の代わりに、EventManager.getAsyncListeners( "SAVE_PRESSED");を呼び出します。
  • このコード/機能は、EventManager によって提供される必要があります。
    • EventManagerに移動した場合、 "* _ COMPLETED"イベントは基本的に非常に特別です。

Promise-awareイベントシステムでは、ハンドラーはシステムに、その時点で有効なオブジェクトを返すだけで非同期であることを通知できます。

5
RonJRH

約束を認識するイベントシステムは、複雑な問題に対する優雅なソリューションを構築するのに役立ちます。ただし、独自のフレームワークを作成するよりも、既存のフレームワークを選択する方が価値があると思います。

私が最もよく使用した(JavaScript)フレームワークはDojoであり、イベント処理コードの強力なコレクションがあります。

これには、前述のように、イベントを連鎖させることが含まれます。先に進む前に一連の約束が解決するのを待つので、すべてが素晴らしいです。

彼らのサイトでいくつかのチュートリアルを実行して、それがあなたのニーズにうまく役立つかどうかを確認することをお勧めします。

2
user2182349

理論的には、純粋なイベントのみで非同期プログラミングを行う適切な方法は、イベントハンドラーが「event_x_completed」イベントを発生させることでしたが、元の「event_x」に対して常に1つのイベントハンドラーが存在することを前提としています。 UIプログラミングでは、そのような仮定はできません。例えば。 1つのユーザーアクションでイベントが発生し、任意の数のUIコンポーネントがトリガーされて更新されます。

えーとイベントハンドラが常に1つだけであると想定する必要はありません。

イベントハンドラは、必要な数だけあります。イベントハンドラーは、そのイベントのハンドラーのリストに自分自身を登録します。

event_x_completed(x_id)は、完了したイベントを正確に通知します。それがタイプxイベントであるというだけでなく、まさに私が待っていたのはxでした。

2つの異なるパラダイムを混在させるのは紛らわしいですが、完全に互換性がないと想定する前に、両方を使用することを知っていることを確認してください。

0
candied_orange