Die durch asynchrone Programmierung verursachten Probleme sind in clientseitigem Javascript nicht offensichtlich, aber da serverseitiges Javascript immer häufiger verwendet wird, macht eine große Anzahl asynchroner E/A-Vorgänge dieses Problem offensichtlich. Es gibt viele verschiedene Möglichkeiten, dieses Problem zu lösen. In diesem Artikel werden einige davon besprochen, aber nicht näher darauf eingegangen. Jeder muss eine Methode wählen, die entsprechend seiner eigenen Situation zu ihm passt.
Dieser Artikel stellt Ihnen die asynchrone Programmierung in js im Detail vor. Der spezifische Inhalt ist wie folgt
1 Über asynchrone Ereignisse
Ereignisse sind die wichtigste Funktion in JavaScript, und nodejs ist so konzipiert, dass es die asynchrone Natur von js nutzt. Lassen Sie uns hier über den Ereignismechanismus sprechen.
Wenn Sie in einer js-Datei eine bestimmte Funktion ausführen möchten, gibt es zwei Möglichkeiten: Eine besteht darin, sie direkt aufzurufen, z. B. foo (), und die zweite darin, sie mithilfe von Ereignissen auszulösen Ruft eine Rückruffunktion auf, z. B. durch Übergabe an die Funktion setTimeout und das Attribut onready.
1. Das Ereignis in der setTimeout-Funktion ist asynchron
setTimeout ist im Wesentlichen ein asynchrones Ereignis, das ausgelöst wird, wenn die Verzögerungszeit abläuft. Allerdings wird es manchmal (tatsächlich meistens) nicht entsprechend der angegebenen Verzögerungszeit ausgeführt Code unten
var start = new Date(); setTimeout(function() { console.log('settimeout1:',new Date()-start); }, 500); while (new Date() - start < 1000) { console.log('in while'); } document.getElementById('test').addEventListener('click', function(){ console.log('test:',new Date()-start); }, false) for(var i=0;i<10000;i++){ console.log('in for'); } setTimeout(function(){ console.log('settimeout2: ',new Date()-start); },1000); /* 10214 in while index.jsp (第 19 行) 10000 in for index.jsp (第 25 行) settimeout1: 2263 index.jsp (第 16 行) settimeout2: 3239 index.jsp (第 28 行) test: 10006 index.jsp (第 22 行) test: 28175 index.jsp (第 22 行) test: 28791 index.jsp (第 22 行) test: 28966 index.jsp (第 22 行) */
Nach normalem Verständnis sollte die Verzögerungsfunktion die While-Schleife nach 500 Millisekunden unterbrechen, aber tatsächlich wurde dies nicht der Fall, als ich während der While-Schleife und der For-Schleife auf das Div klickte Erklärung gegeben Das ist:
a) Ereigniswarteschlange. Wenn die setTimeout-Funktion aufgerufen wird, wird die an sie übergebene Rückruffunktion zur Ereigniswarteschlange hinzugefügt (das Ereignis wurde initialisiert und im Speicher), und dann wird der nachfolgende Code so lange ausgeführt, bis kein Code mehr ausgeführt werden kann (dort). ist kein normaler Laufablauf) (ausgenommen asynchroner Inhalt wie Ereignisfunktionen), wird ein geeignetes Ereignis aus der Ereigniswarteschlange zur Ausführung herausgeholt.
b) js ist Single-Threaded und der Event-Handler wird erst ausgeführt, wenn der Thread inaktiv ist.
2 Die Asynchronität gewöhnlicher Ereignisse ähnelt setTimeout
Zwei Versprechensobjekte und zurückgestellte Objekte
1. Versprechen
Promise ist eine Lösung für das Problem zu vieler verschachtelter Rückruffunktionen in der asynchronen Programmierung wie Ajax, wodurch der Code unklar und schwer verständlich wird. Insbesondere in NodeJS ist Asynchronität überall. Verschiedene Frameworks implementieren Versprechen. Das Folgende ist die Versprechen-API in jquery.
Das Umsetzungsprinzip des Versprechens wird hier nicht besprochen. Das Prinzip wird an anderer Stelle vorgestellt.
Traditionelle asynchrone Ajax-Programmierung wird wie folgt geschrieben (vor jquery1.5):
$.get('url', function(){ $.get('url1', function(){ $.get('url2', function(){ }, 'json'); }, 'json'); }, 'json');
Das Schreiben von Code wie diesem bringt große Schwierigkeiten bei der Entwicklung und Wartung mit sich. Glücklicherweise können Sie ihn nach der Einführung von jquery1.5 wie folgt schreiben:
$.ajax( "example.php" ) .done(function() { alert("success"); }) .fail(function() { alert("error"); }) .always(function() { alert("complete"); });
Es sieht jetzt offensichtlich viel einfacher aus.
2.aufgeschobenes Objekt
var nanowrimoing = $.Deferred(); var wordGoal = 5000; nanowrimoing.progress(function(wordCount) { var percentComplete = Math.floor(wordCount / wordGoal * 100); $('#indicator').text(percentComplete + '% complete'); }); nanowrimoing.done(function(){ $('#indicator').text('Good job!'); });
3. Worker-Objekt und Multithreading
4. Asynchrones Laden von Skripten
1. Die Position traditioneller Skripte auf der Seite
Skripte werden in zwei große Kategorien unterteilt: blockierende und nicht blockierende. Die Blockierung bezieht sich hier eher auf die Ladeblockierung als auf die Laufblockierung.
<!DOCTYPE html> <html> <head> <script src="headScript"></script> <script defer src="deferredScript"></script> </head> <body> <script async defer src="chatWidget"></script> <script async defer src="asyncScript"></script> </body> </html>
Der obige Teil des Codes ist in Bezug auf die Position des Skripts auf einer Seite 1 relativ standardisiert. Das traditionelle, unveränderte HeadScript ist ein blockierendes Skript, da der Browser JavaScript von oben nach unten interpretiert und ausführt wird zu Beginn ausgeführt und das DOM wird nicht gerendert, bevor die Ausführung abgeschlossen ist, aber das CSS im Head-Tag wird geladen. 2. Skripte mit Defer-Attributen werden gleichzeitig mit dem Rendern des DOM geladen, aber erst ausgeführt, wenn das DOM gerendert wird. Leider unterstützen nicht alle Browser das Defer-Attribut, daher wird eine JQuery (Funktion) erstellt . 3. Wenn sowohl das async-Attribut als auch das defer-Attribut vorhanden sind, überschreibt defer async. Wenn jedoch async allein bereitgestellt wird, wird das Skript während des DOM-Renderings geladen und ausgeführt.
2. Programmierbares Laden von Skripten
Wenn Sie js-Dateien nicht von Anfang an in die Seite einführen, sondern js-Skripte dynamisch durch Benutzerinteraktion laden, können Sie sie programmgesteuert hinzufügen.
Es gibt zwei Möglichkeiten für Browser, Serverskripte abzurufen und über die Eval-Funktion auszuführen. Die zweite Methode wird im Allgemeinen verwendet, da der Browser uns dabei hilft Generieren Sie HTTP-Anfragen und werten Sie den Umfang von Lecks aus.
var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.src = '/js/feature.js'; head.appendChild(script); script.onload = function() { // 现在可以调用脚本里定义的函数了 }
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für alle beim Erlernen der asynchronen JS-Programmierung hilfreich ist.