Comment attendre qu'une fonction se termine en JavaScript

Moataz Farid 12 octobre 2023
  1. Synchronisation et asynchronisation en JavaScript
  2. Utilisez le callback pour attendre qu’une fonction se termine en JavaScript
  3. Utilisez promises pour attendre qu’une fonction se termine en JavaScript
  4. Utilisez async/await pour attendre qu’une fonction se termine avant de continuer l’exécution
Comment attendre qu'une fonction se termine en JavaScript

Ce tutoriel présente les fonctions JavaScript Callbacks, Promises et async/await et vous montre comment attendre la fin d’une fonction asynchrone avant de poursuivre l’exécution.

Pour comprendre ce que sont les fonctions Promises et async/await, nous devons d’abord comprendre ce que sont les fonctions sync et async en JavaScript.

Synchronisation et asynchronisation en JavaScript

La programmation synchrone exécute une commande à la fois. Lorsque nous appelons une fonction qui exécute une action de longue durée, elle arrête le programme jusqu’à ce qu’il se termine.

Le JavaScript est traditionnellement monofilaire, même avec plusieurs coeurs. Nous pouvons lui faire exécuter des tâches uniquement sur un seul fil appelé fil principal.

Un tel comportement synchrone est un facteur limitant dans les multi-threads mais aide l’utilisateur à écrire des codes sans se soucier des problèmes de concurrence.

En programmation asynchrone, l’action de longue durée sera exécutée dans un autre thread que le thread principal, de sorte que l’exécution principale n’est pas bloquée. Lorsque cette fonction de longue durée se termine, le programme principal en est informé et a accès aux résultats.

La plupart des primitives d’E/S en JavaScript sont non bloquantes. Les requêtes réseau, les opérations de systèmes de fichiers sont toutes des opérations non bloquantes. Être bloqué est l’exception en JavaScript.

Comme JavaScript est basé sur des techniques de programmation asynchrone, il existe de multiples approches telles que les callbacks, les Promises et les async/await qui vous permettent de mettre en séquence l’exécution de vos fonctions. Ainsi, un bloc de code ou une fonction ne sera pas exécuté avant qu’une autre fonction spécifique ne soit terminée.

sync et async

La figure ci-dessus montre la nette variation entre l’exécution asynchrone et synchrone de deux fonctions.

Utilisez le callback pour attendre qu’une fonction se termine en JavaScript

Si nous avons des déclarations synchrones, alors il est facile d’exécuter ces déclarations l’une après l’autre.

function one() {
  console.log('I am function One');
}
function Two() {
  console.log('I am function Two');
}

one();
Two();

Production :

I am function One 
I am function Two

Supposons que nous voulons exécuter deux fonctions, functionOne() et functionTwo() de telle sorte que functionOne() soit exécutée après avoir exécuté quelques instructions asynchrones à l’intérieur de functionTwo().

function functionOne(_callback) {
  // do some asynchronus work
  _callback();
}

function functionTwo() {
  // do some asynchronus work
  functionOne(() => {
    console.log('I am a callback');
  });
}

functionTwo();

Lors de l’exécution du code ci-dessus, la dernière chose imprimée dans la console est I am a callback. Le célèbre exemple de callback est la fonction setTimeout avec une fonction de gestion à exécuter après le timing out.

function testCallBack() {
  console.log('log before use setTimeout function');
  setTimeout(() => {
    console.log('inside timeout');
  }, 5000);
  console.log('log after use setTimeout function');
}

testCallBack();

Production :

log before use setTimeout function
log after use setTimeout function
inside timeout

Utilisez promises pour attendre qu’une fonction se termine en JavaScript

Une Promises est un objet représentant l’accomplissement ou l’échec éventuel d’une opération asynchrone. Nous attachons le rappel d’exécution à la Promises avec une ou plusieurs instructions then, et quand peut être appelé le rappel du gestionnaire d’erreur dans le catch.

doFirstThing()
    .then(result => doSecondThing(result))
    .then(newResult => doThirdThing(newResult))
    .then(finalResult => {
      console.log('The final result thing' + finalResult);
    })
    .catch(failureCallbackfunction);
}

L’enchaînement des instructions then et catch comme dans l’exemple ci-dessus est l’un des avantages de la promesse. Nous promettons de faire doSecondThing(result) une fois que le doFirstThing() est rempli. Les arguments pour le then sont facultatifs, mais obligatoires si vous devez renvoyer un résultat.

En cas d’erreur, le navigateur cherchera le catch à la fin de la chaîne et l’exécutera. C’est très similaire au fameux try-catch.

L’exemple suivant nous aidera à comprendre les chaînes de Promises et nous montrera comment nous pouvons attendre qu’une fonction au comportement asynchrone termine son exécution avant de pouvoir continuer à l’exécuter.

var resolvedFlag = true;

let mypromise = function functionOne(testInput) {
  console.log('Entered function');
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('Inside the promise');
      if (resolvedFlag == true) {
        resolve('Resolved');
      } else {
        reject('Rejected')
      }
    }, 2000);
  });
};

mypromise()
    .then((res) => {console.log(`The function recieved with value ${res}`)})
    .catch((error) => {
      console.log(`Handling error as we received ${error}`);
    });

Production :

Entered function
Inside the promise
The function received with value Resolved

Créer une promesse peut être aussi simple que de renvoyer une nouvelle Promises. Le constructeur Promise() reçoit une fonction comme argument, qui doit avoir deux paramètres - resolve et reject.

Dans le cas où notre événement est accompli, et que nous devons renvoyer le résultat, nous utilisons la fonction resolve() lorsque nous réussissons ce que nous faisions. Mais si une erreur se produit et doit être traitée, nous utilisons la fonction reject() pour envoyer l’erreur à la fonction catch.

Nous mettons le drapeau resolvedFlag = true pour simuler la gestion des erreurs dans le catch. Si resolvedFlag est réglé sur false, la fonction reject() est appelée, et l’erreur est traitée dans le bloc catch.

Production :

Entered function
Inside the promise
Handling error as we received Rejected

Utilisez async/await pour attendre qu’une fonction se termine avant de continuer l’exécution

Une autre façon d’attendre qu’une fonction s’exécute avant de poursuivre l’exécution dans l’environnement asynchrone en JavaScript est d’utiliser async/wait.

La fonction async est la fonction qui est déclarée par le mot-clé async, alors que seul le mot-clé await est autorisé dans la fonction asyn et utilisé pour suspendre la progression dans la fonction asynchrone jusqu’à ce que l’opération asynchrone basée sur une promesse soit remplie ou rejetée.

Les mots-clés async et await permettent un comportement asynchrone, basé sur la promesse, dans un style plus propre.

Comprenons comment fonctionne la fonction async/await. La fonction que nous attendons doit renvoyer une instance de la classe Promise pour qu’elle attende son exécution en utilisant le mot-clé await avant de l’appeler. Comme mentionné ci-dessus, la fonction qui contient l’instruction await doit être déclarée avec l’instruction async.

L’exemple suivant montre comment attendre la fin de cette fonction basée sur la promesse avant de poursuivre l’exécution.

function testAsync() {
  return new Promise((resolve, reject) => {
    // here our function should be implemented
    setTimeout(() => {
      console.log('Hello from inside the testAsync function');
      resolve();
      ;
    }, 5000);
  });
}

async function callerFun() {
  console.log('Caller');
  await testAsync();
  console.log('After waiting');
}

callerFun();

Production :

Caller
Hello from inside the testAsync function
After waiting

Article connexe - JavaScript Promises