Einführung
Eine leistungsstarke Funktion, die JavaScript so besonders macht, ist die Möglichkeit, asynchron über Callback-Funktionen zu arbeiten. Wenn Sie asynchrone Callbacks zuweisen, können Sie ereignisgesteuerten Code schreiben. Es macht jedoch auch das Aufspüren von Fehlern erschwinglich, da das JavaScript nicht linear ausgeführt wird.
Glücklicherweise finden Sie jetzt in den Chrome-Entwicklertools den vollständigen Aufrufstapel asynchroner JavaScript-Callbacks.
Sobald Sie die asynchrone Aufrufstack-Funktion in den Entwicklertools aktiviert haben, können Sie den Status Ihrer Webanwendung zu verschiedenen Zeitpunkten aufrufen. Durchlaufen Sie den vollständigen Stacktrace für einige Event-Listener, setInterval
, setTimeout
, XMLHttpRequest
, Promise, requestAnimationFrame
, MutationObservers
und mehr.
Während Sie den Stacktrace durchlaufen, können Sie auch den Wert einer Variablen zu diesem bestimmten Zeitpunkt der Laufzeitausführung analysieren. Wie eine Zeitmaschine für Ihre Ausdrücke.
Wir aktivieren diese Funktion und sehen uns einige dieser Szenarien an.
Asynchrones Debugging in Chrome aktivieren
Probiere diese neue Funktion aus, indem du sie in Chrome aktivierst. Gehen Sie in den Chrome Canary-Entwicklertools zum Bereich Quellen.
Rechts neben dem Bereich Aufrufstapel befindet sich das neue Kästchen "Asynchron". Klicken Sie das Kästchen an, um das asynchrone Debugging zu aktivieren oder zu deaktivieren.
Verzögerte Timer-Ereignisse und XHR-Antworten erfassen
Bestimmt haben Sie Folgendes in Gmail schon einmal gesehen:
Wenn es ein Problem beim Senden der Anfrage gibt (entweder treten auf dem Server Probleme auf oder es gibt Probleme mit der Netzwerkverbindung auf Clientseite), versucht Gmail automatisch, die Nachricht nach einer kurzen Zeitüberschreitung noch einmal zu senden.
Um zu sehen, wie asynchrone Aufrufstacks uns helfen können, verzögerte Timerereignisse und XHR-Antworten zu analysieren, habe ich diesen Ablauf mit einem Beispiel für Gmail neu erstellt. Den vollständigen JavaScript-Code findest du unter dem obigen Link. Der Ablauf sieht jedoch so aus:
Da wir uns in früheren Versionen der Entwicklertools nur den Aufrufstapelbereich angesehen haben, würde ein Haltepunkt in postOnFail()
wenig Informationen darüber liefern, von wo postOnFail()
aufgerufen wurde. Beachten Sie jedoch den Unterschied beim Aktivieren asynchroner Stacks:
Wenn asynchrone Aufrufstacks aktiviert sind, können Sie den gesamten Aufrufstack anzeigen. So können Sie leicht feststellen, ob die Anfrage von submitHandler()
(nach dem Klicken auf die Schaltfläche „Senden“) oder von retrySubmit()
(mit einer Verzögerung von setTimeout()
) initiiert wurde:
Ausdrücke asynchron beobachten
Wenn Sie den gesamten Aufrufstack durchlaufen, werden auch die beobachteten Ausdrücke aktualisiert, um den Status wiederzugeben, in dem sie sich zu diesem Zeitpunkt befand.
Code aus früheren Bereichen auswerten
Sie können Ausdrücke nicht nur überwachen, sondern direkt im Steuerfeld der JavaScript-Konsole der Entwicklertools mit dem Code aus vorherigen Bereichen interagieren.
Stell dir vor, du bist Dr. Wer und du brauchst ein wenig Hilfe, um die Uhr aus der Zeit vor deiner Ankunft in der Tardis mit der „jetzt“ zu vergleichen. Über die Entwicklertools-Konsole können Sie Werte aus verschiedenen Ausführungspunkten einfach bewerten, speichern und berechnen.
Wenn Sie Ihre Ausdrücke in den Entwicklertools bearbeiten, sparen Sie Zeit, da Sie nicht zum Quellcode zurückwechseln, Änderungen vornehmen oder den Browser aktualisieren müssen.
Verkettung der Lösungsansätze enthüllen
Wenn Sie dachten, der vorherige simulierte Gmail-Ablauf ohne aktivierte asynchrone Aufrufstack-Funktion wäre schwer zu verstehen, können Sie sich vorstellen, wie viel schwieriger es mit komplexeren asynchronen Abläufen wie verketteten Promis wäre? Sehen wir uns noch einmal das letzte Beispiel der Anleitung von Jake Archibald zu JavaScript Promises an.
Die folgende kleine Animation veranschaulicht die Aufrufstacks in Jakes Beispiel async-best-example.html.
Einblicke in Ihre Webanimationen erhalten
Sehen wir uns die HTML5Rocks-Archive genauer an. Erinnern Sie sich noch an Paul Lewis' Leaner, Meaner, Faster Animations with requestAnimationFrame?
Öffnen Sie die requestAnimationFrame-Demo und fügen Sie einen Haltepunkt am Anfang der Methode update() (um Zeile 874) von post.html ein. Asynchrone Aufrufstacks liefern uns wesentlich mehr Informationen zu requestAnimationFrame, einschließlich der Möglichkeit, bis zum initiierten Scrollereignis-Callback zurückzugehen.
DOM-Aktualisierungen bei Verwendung von MutationObserver finden
Mit MutationObserver
können Änderungen im DOM beobachtet werden. In diesem einfachen Beispiel wird beim Klicken auf die Schaltfläche ein neuer DOM-Knoten an <div class="rows"></div>
angehängt.
Fügen Sie in demo.html einen Haltepunkt innerhalb von nodeAdded()
(Zeile 31) hinzu. Wenn asynchrone Aufrufstacks aktiviert sind, können Sie den Aufrufstack über addNode()
zurück zum ersten Klickereignis leiten.
Tipps für die Fehlerbehebung in JavaScript in asynchronen Aufrufstacks
Funktionen benennen
Wenn Sie alle Callbacks als anonyme Funktionen zuweisen möchten, können Sie ihnen stattdessen einen Namen geben, um das Aufrufen des Aufrufstacks zu erleichtern.
Nehmen wir als Beispiel eine anonyme Funktion wie die folgende:
window.addEventListener('load', function() {
// do something
});
Geben Sie ihm einen Namen wie windowLoaded()
:
window.addEventListener('load', function <strong>windowLoaded</strong>(){
// do something
});
Wenn das Ladeereignis ausgelöst wird, wird es im Stacktrace der Entwicklertools mit seinem Funktionsnamen anstelle der kryptischen „(anonymous function)“ angezeigt. So können Sie auf einen Blick erkennen, was in Ihrem Stacktrace passiert.
Weitere Informationen
Zur Erinnerung: Dies sind alle asynchronen Callbacks, in denen die Entwicklertools den vollständigen Aufrufstack anzeigen:
- Timer: Gehen Sie zurück zur Stelle, an der
setTimeout()
odersetInterval()
initialisiert wurde. - XHRs: Gehen Sie zurück zu der Stelle, an der
xhr.send()
aufgerufen wurde. - Animationsframes: Gehen Sie zurück zu der Stelle, an der
requestAnimationFrame
aufgerufen wurde. - Versprechen: Gehe zu der Stelle, an der ein Versprechen aufgelöst wurde.
- Object.observe: Gehen Sie zurück an die Stelle, an der der Beobachter-Callback ursprünglich gebunden war.
- MutationObservers: Gehen Sie zurück zur Stelle, an der das Mutationsbeobachter-Ereignis ausgelöst wurde.
- window.postMessage(): Führt Intra-Prozess-Messaging-Aufrufe durch.
- DataTransferItem.getAsString()
- FileSystem API
- IndexedDB
- WebSQL
- Zulässige DOM-Ereignisse über
addEventListener()
: Gehen Sie zurück zu der Stelle, an der das Ereignis ausgelöst wurde. Aus Leistungsgründen kommen nicht alle DOM-Ereignisse für die Funktion für asynchrone Aufrufstacks infrage. Beispiele für aktuell verfügbare Ereignisse sind „scroll“, „hashchange“ und „selectionchange“. - Multimedia-Ereignisse über
addEventListener()
: Gehen Sie zurück zur Stelle, an der das Ereignis ausgelöst wurde. Verfügbare Multimedia-Ereignisse: Audio- und Videoereignisse (z.B. "play", "pause", "ratechange"), WebRTC MediaStreamTrackList-Ereignisse (z.B. "addtrack", "removetrack") und MediaSource-Ereignisse (z.B. "sourceopen").
Sie können den vollständigen Stacktrace Ihrer JavaScript-Callbacks sehen. Diese Funktion in den Entwicklertools ist besonders hilfreich, wenn mehrere asynchrone Ereignisse miteinander in Beziehung stehen oder wenn eine nicht abgefangene Ausnahme aus einem asynchronen Callback ausgelöst wird.
Probier es in Chrome aus. Wenn Sie Feedback zu dieser neuen Funktion haben, schreiben Sie uns über den Bug-Tracker der Chrome-Entwicklertools oder in der Gruppe „Chrome DevTools“.