Les problèmes causés par la programmation asynchrone ne sont pas évidents dans le Javascript côté client, mais comme le Javascript côté serveur est de plus en plus largement utilisé, un grand nombre d'opérations d'E/S asynchrones rendent ce problème évident. Il existe de nombreuses façons différentes de résoudre ce problème, et cet article en aborde quelques-unes, mais n'entre pas dans les détails. Chacun doit choisir une méthode qui lui convient en fonction de sa propre situation.
Cet article vous présente en détail la programmation asynchrone en js. Le contenu spécifique est le suivant
1 À propos des événements asynchrones
Les événements sont la fonctionnalité la plus importante de JavaScript, et nodejs est conçu pour tirer parti de la nature asynchrone de js. Parlons donc ici du mécanisme des événements.
Dans un fichier js, si vous souhaitez exécuter une certaine fonction, il existe deux façons de l'appeler directement, comme foo(), et la seconde consiste à utiliser des événements pour la déclencher. appelé une fonction de rappel, par exemple en la transmettant à la fonction setTimeout et à l'attribut onready.
1. L'événement dans la fonction setTimeout est asynchrone
setTimeout est essentiellement un événement asynchrone, qui est déclenché à l'expiration du délai. Cependant, parfois (en fait, la plupart du temps), il ne sera pas exécuté en fonction du délai donné. code ci-dessous
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 行) */
Selon une compréhension normale, la fonction de retard devrait interrompre la boucle while après 500 millisecondes, mais en fait ce n'est pas le cas, lorsque j'ai cliqué sur le div pendant la boucle while et for, le test n'a pas été généré immédiatement. explication donnée C'est à dire :
a) File d'attente des événements. Lorsque la fonction setTimeout est appelée, la fonction de rappel qui lui est transmise sera ajoutée à la file d'attente des événements (l'événement a été initialisé et en mémoire), puis le code suivant continuera à être exécuté jusqu'à ce qu'aucun code ne puisse plus être exécuté (il y a s'il n'y a pas de flux d'exécution normal) (à l'exclusion du contenu asynchrone tel que les fonctions d'événement), un événement approprié sera extrait de la file d'attente des événements pour être exécuté.
b) js est monothread et le gestionnaire d'événements ne s'exécutera pas tant que le thread ne sera pas inactif.
2 L'asynchronie des événements ordinaires est similaire à setTimeout
Deux objets promis et objets différés
1. promesse
Promise est une solution au problème du trop grand nombre de fonctions de rappel imbriquées dans la programmation asynchrone telle que ajax, ce qui rend le code obscur et difficile à comprendre. Surtout dans nodejs, l'asynchrone est partout. Différents frameworks implémentent les promesses. Voici l'API de promesse dans jquery.
Le principe de mise en œuvre de la promesse ne sera pas abordé ici. Le principe sera introduit dans un autre chapitre.
La programmation asynchrone ajax traditionnelle est écrite comme ceci (avant jquery1.5) :
$.get('url', function(){ $.get('url1', function(){ $.get('url2', function(){ }, 'json'); }, 'json'); }, 'json');
L'écriture de code comme celui-ci entraîne de grandes difficultés de développement et de maintenance. Heureusement, après l'introduction des promesses de jquery1.5, vous pouvez l'écrire comme ceci :
$.ajax( "example.php" ) .done(function() { alert("success"); }) .fail(function() { alert("error"); }) .always(function() { alert("complete"); });
Cela semble évidemment beaucoup plus simple maintenant.
2.objet différé
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. Objet Worker et multi-threading
4. Chargement de script asynchrone
1. La position des scripts traditionnels dans la page
Les scripts sont divisés en deux grandes catégories : bloquants et non bloquants. Le blocage fait ici référence au blocage de chargement plutôt qu'au blocage en cours d'exécution.
<!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>
La partie ci-dessus du code est relativement standard concernant la position du script dans une page. 1. Le headScript traditionnel non modifié est un script bloquant puisque le navigateur interprète et exécute JavaScript de haut en bas, ce qui le fera. sera exécuté au début, et le DOM ne sera pas rendu avant la fin de l'exécution, mais le CSS dans la balise head sera chargé. 2. Les scripts avec des attributs defer seront chargés en même temps que le rendu du DOM, mais ne seront pas exécutés tant que le DOM ne sera pas rendu. Malheureusement, tous les navigateurs ne prennent pas en charge l'attribut defer, donc jquery (fonction) est créé. . 3. Lorsque les attributs async et defer sont présents, defer remplacera async, mais lorsque async est fourni seul, le script sera chargé et exécuté pendant le rendu DOM.
2. Chargement de script programmable
Si vous n'introduisez pas de fichiers js dans la page depuis le début, mais chargez dynamiquement des scripts js via l'interaction de l'utilisateur, vous pouvez les ajouter par programme.
Il existe deux manières pour les navigateurs d'obtenir les scripts du serveur. Ajax les obtient et les exécute via la fonction eval. L'autre consiste à insérer la balise