イベントが既に発生した後にアタッチされた場合、イベントリスナーを呼び出す必要がありますか?


8

イベントがすでに発生した後に接続されている場合、イベントリスナーを呼び出す必要がありますか?イベントが一度だけ発生する場合はどうなりますか?

頭に浮かぶ最初の例は、readyjQuery のイベントです。次のスニペットは、ページが読み込まれた後に評価されると、コールバックを呼び出します。

$(document).ready(function () {
    console.log("Works.");
});

この動作の代わりに、ページが読み込まれたときに設定されるフラグを使用して、APIのコンシューマーに、イベントがすでに発生しているかどうかを確認し、それに応じて動作するように強制することができます。

if (document.readyState == "complete") {
    console.log("Works.");
} else {
    $(document).ready(function () {
        console.log("Works.");
    });
}

上記の例は、ページが完全にロードされた後に何でも(通常は)すべてを実行する必要があるWebページのロードのコンテキストですが、「singleton」イベントを持つアプリケーションの単一のコンポーネントに対して同じ引数を作成できます(loadstartend、など)。単一成分の例は、とマップすることができload、イベント起動マップが読み込まれ、そのように指定すること

map.on("load", function () {
    console.log("The map has loaded.");
});

上記の例は、ArcGIS API for JavaScriptからのもので、そのイベントは1回だけ発生します。コンシューマーがマップがロードされた後にマップがロードされるのを「待機」した場合、リスナーは呼び出されません。望ましい結果を得るには、リスナーをアタッチする前にマップの状態を確認する必要があります

if (map.loaded) {
    console.log("The map has loaded.");
} else {
    map.on("load", function () {
        console.log("The map has loaded.");
    });
}

イベントが既に発生しているか、または常にコールバックを呼び出しているかどうかをコンシューマーに要求する正しい動作はどれですか。


5
反応Extensionsのに興味がされる可能性がありますSubjectReplaySubject前者がないのに対し、後半の加入者のために後者のリプレイ前のイベント。つまり、Rxの作成者は、1つの明確な動作を決定するのではなく、両方の動作をモデル化しました。-上記のリンクはRxの.NETバージョンのドキュメントに移動しますが、JavaScript用Rxもあります
stakx 2014年

回答:


19

それは、それが本当にイベントであるか状態通知であるかによって異なります(準備ができているかどうか)。それがイベントである場合、以前のすべてのイベントについてリスナーに通知する必要はありません。状態通知の場合は、サブスクライブした直後に指定した状態になったことを伝えます。

トリッキーなビットは、それをどのように見るかに応じて、状態またはイベントのいずれかになり得ます-最悪の場合、それはドキュメントによって説明されます。せいぜい、あなたが何を意味するのかを明確にする良い名前を選んでください。


2
+1、状態通知について言及するため。状態通知は、たとえばScala(docs.scala-lang.org/overviews/core/futures.html)のフューチャーとコールバックの処理に近いIMO です。
Giorgio 14年

興味深いことに、私はそのようなことを考えていませんでした。あなたは分類するloadstartまたはend同じready状態通知として、?
Whymarrh 2014年

@Whymarrh:状況によって異なりますが、これらは私にはイベントのように聞こえます。私は状態通知を質問として名前を付ける傾向があります...準備はいいですか?始めた?ランニング?もちろん、既存の命名規則に合わせる必要があるかもしれません。
jmoreno 2014年

3
イベントは、状態を変更するために一度発生したものとして解釈できるように思えます。つまり、彼らは非常に短命であり、実際には一瞬です。一方、状態は長命であり、複数の瞬間から構成されます。loadイベントでも状態でもありません。loadingStartedイベントでloadingあり、状態です。
Jeroen Vannevel 2014

5

通常、いいえ

イベントリスナは、イベントが既に発生した後に接続されている場合は呼び出さないでください。「あなたは居眠りして、あなたは失います。」

いくつかの重要な例外があります。$(document).ready()おそらく完璧な例です。その前に、評価コンテキスト全体が確実にまたは完全に確立されておらず、「全機能処理がここから始まる」マーカーとして機能するイベント。

ただし、イベントが発生した後にイベントハンドラーをインストールまたはアクティブ化した場合でも、イベントハンドラーを起動するというルールを設定した場合は、すべてのイベントをプログラム実行の最初から最後までバッファリングするか、またはバッファリングする必要があることを宣言しました。考えられるすべてのイベント。それ以外の場合は、イベントのどこかでイベントハンドラーが確立されている可能性があります。イベントハンドラーは、確立されたときに起動する必要があるかどうかを知るのに十分な情報を持っていません。つまり、考えられるすべてのイベントソースを計測し、それらすべてを無限にバッファリングする必要があります。遅延評価(およびそのすべてのパフォーマンス上の利点)から熱心な評価まで、イベント処理を行います。そして、スペクトルの遠端にあるものに。後で処理する必要がある可能性のあるイベントについての壊滅的な仮定に基づく狂信的な評価?

イベントは一時的で多数の傾向があります。それらが最終的にタップされる可能性について、制限なしに、それぞれをバッファリングする必要があるルールを設定します。さらに、ハンドラーは一般的にプログラムの早い段階で確立できるため、そうするための大きな要件はありません。

ルールの例外はエッジケースです。たとえば、ドキュメントまたはサブシステムの読み込みは、他の方法ではキャプチャまたは処理できない不可欠で一意の主要なイベントです。これは「シングルトン」イベントに非常に近いものです。特別な処理が必要になる可能性がある別のグループは、重大なエラー、セキュリティイベント、またはイベントの発生時にフラグのサブスクライバーがいない場合でもフラグを立てる必要がある例外的なステータス変更です。

最後に、「準備完了」イベントは「ロード」イベントとは微妙に異なります。それらは明確に区別されないことがよくありますが(たとえば、HTML onloadとjQuery $(document).ready()は論理的に非常に類似していると見なされます)、どちらもリソースまたは処理環境の可用性を通知しますが、まったく同じではありません。読み込み(またはその終了)は本当のイベントです。インフラストラクチャから消費者に何かが通知されます。ただし、準備はランデブーよりもインフラストラクチャによるリソース/環境の読み込み、およびコンシューマがその可用性を利用/利用する準備ができるように準備を整えています。準備はロード後に行われ、他の方法ではキャプチャできないため、キュー可能として処理する必要がある指定された特別なイベント/調整ポイントの1つです。ただし、非常に特殊なケースがいくつかあることは、すべてのイベントが事後的に発生可能であることを意味するわけではありません。


えーと、htmlの「onload」という意味ですか?
StarWeaver

@StarWeaverありがとう。私が滑ったのか、私の野心的なオートコレクトが滑ったのかはわかりませんが、あなたは完全に正しいです。修繕。
Jonathan Eunice 14

NP、私はhtmlポスト4に完全には満足していませんが、奇妙に聞こえました。いい説明も。
StarWeaver
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.