Sollte ein Ereignis-Listener aufgerufen werden, wenn er angehängt ist, nachdem das Ereignis bereits ausgelöst wurde? Was ist, wenn das Ereignis nur einmal ausgelöst wird?
Das erste Beispiel, das mir in den Sinn kommt, ist das ready
Ereignis in jQuery. Das folgende Snippet ruft nach dem Laden der Seite den Rückruf auf:
$(document).ready(function () {
console.log("Works.");
});
Die Alternative zu diesem Verhalten könnte ein Flag sein, das beim Laden der Seite gesetzt wird und den Verbraucher der API dazu zwingt, zu überprüfen, ob das Ereignis bereits eingetreten ist, und entsprechend zu handeln:
if (document.readyState == "complete") {
console.log("Works.");
} else {
$(document).ready(function () {
console.log("Works.");
});
}
Während das obige Beispiel im Zusammenhang mit dem Laden einer Webseite steht, bei der (normalerweise) alles und jedes geschehen muss, nachdem die Seite vollständig geladen wurde, können dieselben Argumente für jede einzelne Komponente in einer Anwendung mit "Singleton" -Ereignissen vorgebracht werden ( load
, start
, end
, usw.). Ein Beispiel für eine einzelne Komponente könnte eine Karte mit einem load
Ereignis sein , das ausgelöst wird, um anzugeben, dass die Karte geladen wurde :
map.on("load", function () {
console.log("The map has loaded.");
});
Das obige Beispiel stammt aus der ArcGIS-API für JavaScript, in der dieses Ereignis nur einmal ausgelöst wird. Wenn ein Verbraucher darauf wartet, dass die Karte geladen wird, nachdem die Karte bereits geladen wurde, wird der Listener niemals aufgerufen. Für das gewünschte Ergebnis muss der Status der Karte überprüft werden, bevor der Listener angehängt wird:
if (map.loaded) {
console.log("The map has loaded.");
} else {
map.on("load", function () {
console.log("The map has loaded.");
});
}
Welches Verhalten ist korrekt, wenn der Verbraucher überprüfen muss, ob ein Ereignis bereits ausgelöst wurde, oder immer den Rückruf aufruft?
quelle
Subject
vs. interessiert seinReplaySubject
, bei denen letzterer frühere Ereignisse für späte Abonnenten wiedergibt, während ersterer dies nicht tut. Das heißt, die Entwickler von Rx haben beide Verhaltensweisen modelliert, anstatt sich für ein bestimmtes Verhalten zu entscheiden. - Während die obigen Links zur Dokumentation der .NET-Version von Rx führen, gibt es auch einen Rx für JavaScript .Antworten:
Das hängt davon ab, ob es sich wirklich um eine Ereignis- oder Statusbenachrichtigung handelt (was bereit ist). Wenn es sich um ein Ereignis handelt, informieren Sie den Listener nicht über alle vorherigen Ereignisse. Wenn es sich um eine Statusbenachrichtigung handelt, teilen Sie dies ihnen sofort mit, nachdem sie sich angemeldet haben und Sie sich im angegebenen Status befinden.
Das Knifflige wird sein, wo es entweder ein Zustand oder ein Ereignis sein kann, je nachdem, wie Sie es betrachten - im schlimmsten Fall wird dies durch die Dokumentation erklärt. Bestenfalls wählen Sie einen guten Namen, der klar macht, was Sie meinen.
quelle
load
,start
oderend
die gleiche wieready
als Zustand Meldung?load
ist weder ein Ereignis noch ein Staat.loadingStarted
ist ein Ereignis undloading
ist ein Staat.Im Allgemeinen nein .
Ereignis-Listener sollten nicht aufgerufen werden, wenn sie angehängt sind, nachdem das Ereignis bereits ausgelöst wurde. "Wenn du einschläfst, verlierst du."
Es gibt einige wichtige Ausnahmen.
$(document).ready()
ist vielleicht das perfekte Beispiel - ein Ereignis, vor dem der gesamte Bewertungskontext nicht zuverlässig oder vollständig hergestellt ist und das als Marker "Vollfunktionsverarbeitung beginnt hier" dient.Wenn Sie jedoch die Regel festlegen, dass ein Ereignishandler auch dann ausgelöst werden soll, wenn er nach dem Eintreten des Ereignisses installiert und / oder aktiviert wird, haben Sie erklärt, dass alle Ereignisse vom Beginn bis zum Ende des Programmlaufs gepuffert werden sollen oder müssen. für jedes denkbare Ereignis. Andernfalls werden möglicherweise Ereignisbehandlungsroutinen für ein Ereignis eingerichtet, das irgendwo in der Zukunft nicht über ausreichende Informationen verfügt, um zu wissen, ob Sie bei der Einrichtung feuern sollten. Das bedeutet, dass Sie jede mögliche Ereignisquelle instrumentieren und auch jede von ihnen unendlich puffern müssen. Dies führt die Ereignisverarbeitung von der verzögerten Bewertung (und all ihren Leistungsvorteilen) bis zur eifrigen Bewertungund auf alles, was sich am anderen Ende des Spektrums befindet. Frenetische Bewertung basierend auf katastrophalen Annahmen darüber, welche Ereignisse später behandelt werden müssen?
Ereignisse sind in der Regel vorübergehend und zahlreich. Das Festlegen von Regeln, nach denen die einzelnen Regeln ohne Einschränkung gepuffert werden müssen, um die Möglichkeit zu gewährleisten, dass sie irgendwann abgerufen werden - das ist Leistungsselbstmord. Darüber hinaus besteht keine große Voraussetzung dafür, da Handler in der Regel früh im Programmleben eingerichtet werden können.
Ausnahmen von der Regel sind Randfälle - beispielsweise das Laden von Dokumenten oder Subsystemen, bei denen es sich um wesentliche, eindeutige Großereignisse handelt, die ansonsten nicht erfassbar oder handhabbar sind. Dies ist sehr nah an Ihren "Singleton" -Ereignissen. Eine andere Gruppe, die möglicherweise eine besondere Behandlung benötigt, sind erhebliche Fehler, Sicherheitsereignisse oder Statusänderungen, die in Ausnahmefällen gekennzeichnet werden müssen, selbst wenn zum Zeitpunkt des Ereignisses keine Abonnenten für das Kennzeichen vorhanden sind.
Ein letzter Hinweis: Ein "Bereit" -Ereignis unterscheidet sich geringfügig von einem "Lade" -Ereignis. Obwohl sie oft nicht klar voneinander unterschieden sind (z. B. HTML
onload
und jQuery$(document).ready()
als logisch sehr ähnlich angesehen werden) und beide die Verfügbarkeit einer Ressource oder Verarbeitungsumgebung signalisieren, sind sie nicht ganz gleich. Das Laden (oder das Beenden davon) ist ein echtes Ereignis - etwas, das von der Infrastruktur an den Verbraucher signalisiert wird. Bereitschaft ist jedoch eher das RendezvousWenn die Infrastruktur die Ressource / Umgebung lädt und der Verbraucher bereit ist, diese Verfügbarkeit zu nutzen. Die Bereitschaft erfolgt nach dem Laden und ist eines der festgelegten Sonderereignisse / Koordinierungspunkte, die als Warteschlange behandelt werden müssen, da Sie sie nicht auf andere Weise erfassen können. Dass es einige ganz besondere Fälle gibt, bedeutet jedoch nicht, dass jedes Ereignis a posteriori ausgelöst werden sollte .quelle