JavaScript und mehr: 4 kreative Ansätze zur Zeitmessung in Browsern

Der Autor des Artikels, dessen Übersetzung wir heute veröffentlichen, hat beschlossen, über einige ungewöhnliche Methoden zur Zeitmessung in Browsern zu sprechen. Um sie verwenden zu können, benötigen Sie Zugriff auf verschiedene APIs, die in der Webentwicklung verwendet werden. Daher sind sie nicht für die Node.js-Plattform geeignet. Wenn jemand eine ungewöhnliche Methode zur Zeitmessung in Node.js benötigt, haben wir nach dem Lesen dieses Materials möglicherweise einige Ideen zu diesem Thema.



Verwenden einer Endlossynchronschleife in einem Web-Worker (nicht in einem Service-Worker)


Da Web-Worker im Wesentlichen Threads sind, die in einem Webbrowser ausgeführt werden, können sie Endlosschleifen ausführen, ohne das Risiko einzugehen, den Haupt-Thread zu blockieren. Auf diese Weise können Sie mit Zeiträumen arbeiten, deren Dauer weniger als eine Millisekunde beträgt. Diese Genauigkeit eignet sich besonders für Fälle, in denen ein Mitarbeiter Entscheidungen treffen muss, die stark zeitabhängig sind. Die Annahme dieser Entscheidungen kann (mit sehr hoher Genauigkeit) dem Hauptstrom gemeldet werden. Sie können beispielsweise etwas ableiten, wenn die Anzahl der Mikrosekunden, die seit einem bestimmten Ereignis vergangen sind, durch eine Primzahl dargestellt wird. Um im Laufe der Zeit mit einer Genauigkeit von Mikrosekunden zu arbeiten, können Sie die Methode performance.now verwenden .

▍Vorteile


  1. Erreichbare Genauigkeit in Mikrosekunden.
  2. .
  3. , , . - .
  4. . , setInterval, terminate , . MDN : « terminate() Worker . , ».


  1. Obwohl diese Methode es ermöglicht, mit Zeitintervallen von weniger als einer Millisekunde zu arbeiten, funktioniert das Senden von Nachrichten an den Hauptthread asynchron. Das heißt, es ist unmöglich, bestimmte Aktionen im Haupt-Thread mit der gleichen Genauigkeit auszuführen, mit der der Arbeiter entscheidet, dass diese Aktionen ausgeführt werden müssen.
  2. Diese Methode lädt den Stream vollständig, was zu einem erhöhten Batterieverbrauch bei Telefonen führen kann.
  3. Diese Methode erfordert die Unterstützung von Web-Workern.
  4. Eine Endlosschleife in einem Web Worker wird nicht angehalten, wenn die zugehörige Registerkarte inaktiv ist.

Beispiel für Codesandbox

Verwenden von CSS-Animationen für zeitbezogene Ereignisse (insbesondere - Animationsiteration)


Bei dieser Methode wird ein Element mit endlosen Animationen erstellt. Hier können Sie versuchen, das Element zu verwenden div, aber ich muss sagen, dass es, wie in Absatz 2 der Liste der Mängel dieser Methode erwähnt, divbesser ist, keine Elemente für diese Zwecke zu verwenden. Wenn wir also ein Element mit endlosen Animationen haben, können wir sein Ereignis abonnieren animationiterationund Benachrichtigungen erhalten, wenn das Intervall abläuft animation-duration.

▍Vorteile


  1. Automatisch pausieren, wenn die Browser-Registerkarte inaktiv wird. In diesem Fall tritt das für uns interessante Ereignis einfach nicht ein. Daher müssen Sie sich nicht um die Lösung des Problems kümmern, viele Ereignisse zu verarbeiten, die sich während der Zeit angesammelt haben, als die Registerkarte inaktiv war und dann aktiviert wurde.
  2. div DOM. , React-, , . div .
  3. , , . — :

    .addEventListener("animationiteration", fun).
  4. animation-delay.


  1. . , , .
  2. Abhängigkeit von DOM und CSSOM. Andere CSS-Regeln können sich auf diejenigen auswirken, die die Animation beschreiben. Daher empfehle ich Ihnen, für die Organisation des Timers eine Art zufällig benanntes, zuvor nicht vorhandenes Tag wie zu erstellen <just-a-timer-element></<just-a-timer-element>. Vielleicht - lohnt es sich, ein benutzerdefiniertes Element zu erstellen, in dem der CSS-Animationscode ordentlich versteckt ist? (All dies sind eigentlich ziemlich kontroverse Ideen).
  3. Diese Methode funktioniert nicht, wenn das Element einen Stil hat display: none;.
  4. Ungenauigkeit. Gemäß meinen Tests kann die Genauigkeit des Countdowns etwa 1 ms betragen. Um genau herauszufinden, wie es für Sie funktioniert, können Sie mit einem Beispiel experimentieren, auf das unten ein Link verweist.

Beispiel für Codesandbox

Verwenden des SVG-Tags (SMIL-Animationen)


Schauen Sie sich das folgende SVG-Element an:

<svg>
  <rect>
    <animate
      attributeName="rx"
      values="0;1"
      dur="1s"
      repeatCount="indefinite"
    />
  </rect>
</svg>

Wenn Sie den folgenden Code verwenden: animate.addEventListener('repeat', fun)wird die Funktion funjede durSekunde aufgerufen . In unserem Fall jede Sekunde.

▍Vorteile


  1. Diese Methode funktioniert auch dann, wenn dem SVG-Element ein Stil zugewiesen ist display: none;.
  2. Der Countdown stoppt automatisch, wenn das SVG-Element aus dem DOM entfernt wird.
  3. Die Ereignisgenerierung wird erst gestartet, wenn die Seite vollständig geladen ist.
  4. Der "Timer" wird automatisch angehalten, wenn die Registerkarte inaktiv wird.

▍ Nachteile


  1. Wie beim Zählen von Zeitintervallen mithilfe von CSS-Animationen kann die Anwendung dieser Methode für andere Programmierer unverständlich erscheinen.
  2. Abhängigkeit von DOM und CSSOM. Das heißt - hier haben wir die gleichen unerwünschten Funktionen, die bereits für die Methode zum Zählen der Zeit mithilfe von CSS-Animationen beschrieben wurden. Nämlich - die Möglichkeit einer Unterbrechung des "Timers" aufgrund anderer CSS-Regeln.
  3. Es wird in IE und Edge nicht unterstützt (bis der Browser von Microsoft auf Chromium übertragen wird).
  4. Ungenauigkeit. Nach meinen Tests können die Abweichungen eines solchen Timers von der genauesten Methode sehr beeindruckende 15 Millisekunden betragen. Sie können dies selbst überprüfen, indem Sie mit dem Beispiel experimentieren, auf das unten ein Link verweist.
  5. Der Countdown startet erst, wenn die Seite vollständig geladen ist. Dieses „Minus“ dieser Methode kann sich in einigen Situationen als „Plus“ herausstellen.

Beispiel für Codesandbox

Verwenden der Webanimations-API


Mit der Webanimations-API können Sie DOM-Elemente mithilfe von JavaScript-Code animieren.

Das Interessante ist, dass Sie sogar unmontierte Elemente animieren können! Auf diese Weise erhalten Sie Zugriff auf die Zeitmechanismen, die in reinem JavaScript (und der Web-API) verfügbar sind.

Hier ist eine alternative Implementierung setTimeout:

function ownSetTimeout(callback, duration) {
  const div = document.createElement('div');

  const keyframes = new KeyframeEffect(div, [], { duration, iterations: 1 });

  const animation = new Animation(
    keyframes,
    document.timeline
  );

  animation.play();

  animation.addEventListener('finish', () => {
    callback();
  });
}

Ordentlich, richtig?

▍Vorteile


  1. Eine in sich geschlossene Lösung, die keine Interaktion mit dem DOM erfordert.
  2. Ein Programmierer, der mit diesem Ansatz nicht vertraut ist, wird die Bedeutung des entsprechenden Codes leicht verstehen.
  3. "Timer" wird auf einer inaktiven Registerkarte angehalten.

▍ Nachteile


  1. Web Animations API - die Technologie ist noch experimentell. Verwenden Sie es nicht in der Produktion.
  2. Sehr schlechte Browserunterstützung. Diese Methode funktioniert wahrscheinlich nur in Chrom.
  3. Mit all den Vorteilen dieser Lösung mag es dennoch jemandem weit davon entfernt erscheinen, intuitiv zu sein.
  4. Die Tatsache, dass der „Timer“ auf einer inaktiven Registerkarte angehalten wird, kann sich als Minus dieser Lösung herausstellen, wenn sie als Alternative verwendet wird setTimeout.
  5. Diese Methode kann nicht zum Zählen von Intervallen verwendet werden. Dem Programmierer steht nur eine Veranstaltung zur Verfügung onfinish.
  6. Geringe Genauigkeit. Nach meinen Experimenten kann der Fehler leicht ± 5 Millisekunden betragen.

→  Beispiel für Codesandbox

Bonus


Um mit der Zeit zu arbeiten, können Sie die Web-Audio-API verwenden. Dies ist eine weitere großartige Möglichkeit, um mit Intervallen und Verzögerungen genau zu arbeiten. Hier ist ein großartiger Artikel darüber.

Zusammenfassung


Ich verstehe, dass die hier aufgeführten Techniken des Arbeitens mit der Zeit bei weitem von allen profitieren können. Aber ich konnte einfach nicht anders, als diesen Artikel zu schreiben, weil ich immer dachte, dass setTimeoutund setInterval- dies die einzigen Möglichkeiten für asynchrones Arbeiten mit bestimmten Zeitintervallen sind. Aber in Wirklichkeit ist dies, wie sich herausstellte, alles andere als alles. Wer weiß, vielleicht muss sich jemand bei der Arbeit an einem bestimmten Projekt mit ungewöhnlichen Einschränkungen auseinandersetzen, unter bestimmten Bedingungen, unter denen sich die hier hervorgehobenen Arbeitsmethoden im Laufe der Zeit als nützlich erweisen können.

Liebe Leser! In welchen Situationen können sich die hier beschriebenen zeitbasierten Ansätze Ihrer Meinung nach als nützlich erweisen?


All Articles