Dans le développement de sites Web, les événements asynchrones sont une partie inévitable du projet. De plus, en raison de l'essor des frameworks front-end, le SPA implémenté via des frameworks est devenu un standard pour la création rapide de sites Web. L'obtention de données est devenue un élément indispensable ; cet article parlera du traitement asynchrone en JavaScript.
Tout d'abord, bien sûr, vous devez comprendre ce que signifient respectivement synchrone et asynchrone.
Ces deux termes prêtent toujours à confusion pour les débutants. Après tout, le sens littéral en chinois est facile à comprendre à l'envers. Du point de vue des sciences de l'information, la synchronisation fait référence à Faire les choses une par une, alors que de manière asynchrone, c'est quand. beaucoup de choses sont traitées ensemble en parallèle.
Par exemple, lorsque nous allons à la banque pour gérer des affaires, faire la queue devant la fenêtre est une exécution synchrone, et obtenir le numéro et faire d'autres choses en premier est une exécution asynchrone grâce aux caractéristiques de la boucle d'événement, les événements asynchrones peuvent être dits en JavaScript C'est un jeu d'enfant
Alors, quelle est la façon de gérer les événements asynchrones en JavaScript ?
Celle que nous connaissons le mieux est la fonction de rappel. Par exemple, les écouteurs d'événements enregistrés lorsqu'une page Web interagit avec les utilisateurs doivent recevoir une fonction de rappel ; ou diverses fonctions d'autres API Web telles que setTimeout
et xhr
peuvent également transmettre des fonctions de rappel à la demande de l'utilisateur pour se déclencher. Regardons d'abord un exemple de setTimeout
:
// callback function withCallback() { console.log('start') setTimeout(() => { console.log('callback func') }, 1000) console.log('done') }withCallback() // start // done // callback func
Après l'exécution de setTimeout
, lorsque l'intervalle de temps spécifié sera écoulé, la fonction de rappel sera placée à la fin de la file d'attente et attendra l'événement boucle pour le traiter.
Remarque : en raison de ce mécanisme, l'intervalle de temps défini par le développeur sur setTimeout
ne sera pas exactement égal au temps écoulé entre l'exécution et le déclenchement. Faites particulièrement attention lorsque vous l'utilisez !
Bien que les fonctions de rappel soient très courantes en développement, elles présentent également de nombreux problèmes difficiles à éviter. Par exemple, comme les fonctions doivent être transmises à d'autres fonctions, il est difficile pour les développeurs de contrôler la logique de traitement dans d'autres fonctions et comme la fonction de rappel ne peut coopérer qu'avec try … catch
pour capturer les erreurs, il est difficile de contrôler quand un une erreur asynchrone se produit ; en outre, il existe le plus célèbre « enfer de rappel ».
Heureusement, Promise est apparu après ES6 et a sauvé les développeurs piégés en enfer. Son utilisation de base est également très simple :
function withPromise() { return new Promise(resolve => { console.log('promise func') resolve() }) } withPromise() .then(() => console.log('then 1')) .then(() => console.log('then 2')) // promise func // then 1 // then 2
Ce qui n'a pas été mentionné lors de la discussion sur Event Loop auparavant, c'est que dans la norme HTML 5 Web API, Event Loop ajoute une file d'attente de micro-tâches et Promise It est piloté par la microtâche. file d'attente ; le moment de déclenchement de la file d'attente des microtâches est lorsque la pile est effacée. Le moteur JavaScript confirmera d'abord s'il y a quelque chose dans la file d'attente des microtâches. S'il y a quelque chose, il sera exécuté en premier et ne sera retiré de la file d'attente qu'après. il est effacé. Placez de nouvelles tâches sur la pile.
Comme dans l'exemple ci-dessus, lorsque la fonction renvoie une promesse, le moteur JavaScript placera la fonction transmise dans la file d'attente des microtâches, effectuera une boucle à plusieurs reprises et affichera les résultats répertoriés ci-dessus. La syntaxe .then
suivante renverra une nouvelle promesse et la fonction de paramètre recevra le résultat du Promise.resolve
précédent. Avec le passage de ce paramètre de fonction, les développeurs peuvent traiter les événements asynchrones en séquence de manière pipeline.
Si vous ajoutez setTimeout
à l'exemple, vous comprendrez plus clairement la différence entre les microtâches et les tâches générales :
function withPromise() { return new Promise(resolve => { console.log('promise func') resolve() }) } withPromise() .then(() => console.log('then 1')) .then(() => setTimeout(() => console.log('setTimeout'), 0)) .then(() => console.log('then 2')) // promise func // then 1 // then 2 -> 微任务优先执行 // setTimeout
De plus, les erreurs asynchrones difficiles à gérer avec le rappel fonction mentionnée précédemment, elle peut également être capturée via la syntaxe .catch
.
function withPromise() { return new Promise(resolve => { console.log('promise func') resolve() }) } withPromise() .then(() => console.log('then 1')) .then(() => { throw new Error('error') }) .then(() => console.log('then 2')) .catch((err) => console.log('catch:', err)) // promise func // then 1 // catch: error // ...error call stack
Depuis l'avènement d'ES6 Promise, le code asynchrone est progressivement passé de l'enfer des rappels à un traitement de pipeline fonctionnel élégant, mais pour ceux qui ne sont pas familiers avec Pour les développeurs, cela passe simplement de l'enfer des rappels à l'enfer des promesses.
a standardisé le nouveau async
/await
dans ES8. Bien qu'il ne s'agisse que d'un sucre syntaxique pour combiner Promise et Generator Function, les événements asynchrones peuvent être synchronisés via async
/await
Géré avec la grammaire, c'est comme un vieil arbre qui fleurit de nouvelles fleurs. Le style d'écriture est complètement différent de Promise :
function wait(time, fn) { return new Promise(resolve => { setTimeout(() => { console.log('wait:', time) resolve(fn ? fn() : time) }, time) }) } await wait(500, () => console.log('bar')) console.log('foo') // wait: 500 // bar // foo
est empaqueté dans Promise en enveloppant setTimeout
dans Promise, puis appelé en utilisant le mot-clé await
, comme vous. peut voir Le résultat sera une exécution synchrone avec bar
apparaissant en premier, puis foo
, qui est l'événement asynchrone écrit comme traitement synchrone mentionné au début.
Regardez un autre exemple :
async function withAsyncAwait() { for(let i = 0; i < 5; i++) { await wait(i*500, () => console.log(i)) } }await withAsyncAwait() // wait: 0 // 0 // wait: 500 // 1 // wait: 1000 // 2 // wait: 1500 // 3 // wait: 2000 // 4
implémente la fonction withAsyncAwait
dans le code et utilise la boucle for
et le mot-clé await
pour exécuter à plusieurs reprises la fonction wait
; lorsqu'elle est exécutée ici, chaque boucle attendra un nombre différent de secondes dans l'ordre avant d'exécuter la boucle suivante.
Lors de l'utilisation de async
/await
, puisque le mot-clé await
ne peut être exécuté qu'en fonction asynchrone, n'oubliez pas de l'utiliser en même temps.
De plus, lorsque vous utilisez des boucles pour traiter des événements asynchrones, vous devez noter que de nombreuses méthodes Array fournies après ES6 ne prennent pas en charge la syntaxe async
/await
si vous utilisez forEach
au lieu de for
ici. , le résultat deviendra une exécution synchrone, imprimera des nombres toutes les 0,5 secondes :
Cet article présente brièvement trois manières dont JavaScript gère le traitement asynchrone et illustre le codez à travers quelques exemples simples La séquence d'exécution fait écho à la boucle d'événements mentionnée précédemment et ajoute le concept de file d'attente de microtâches. J'espère que cela vous aidera à comprendre les applications synchrones et asynchrones.
Pour plus de connaissances sur la programmation, veuillez visiter : Introduction à la programmation ! !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!