Maison  >  Article  >  interface Web  >  Comprendre comment l'asynchronie est gérée en JavaScript

Comprendre comment l'asynchronie est gérée en JavaScript

青灯夜游
青灯夜游avant
2020-11-20 17:29:059339parcourir

Comprendre comment l'asynchronie est gérée en JavaScript

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.

Synchroniser ? asynchrone?

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 ?

Fonction de rappel

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 ».

Promise

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

async wait

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 :

Résumé

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer