Qu'est-ce qu'une requête asynchrone ?
#1 Requête asynchrone qu'est-ce que ça veut dire ?
Lorsqu'un programme, quel qu'il soit, fait une requête, il fait toujours une demande puis reçoit une réponse. Il s'écoule inévitablement un temps entre la demande et la réponse. 😎
Le programme a deux solutions pour gérer la situation :
- Il envoie la demande et se bloque en attendant la réponse. Dans ce cas, la requête est dite synchrone.
- Il envoie la demande et continue son exécution. Il traitera la réponse quand elle arrivera. Dans ce cas, la requête est dite asynchrone.
Etre capable de travailler avec des requêtes asynchrones n'est pas spécifique à JavaScript. Vous retrouvez cette possibilité dans tout un tas de langages : C++, PHP, Python. En fait, cette capacité ne dépend pas du langage, mais plutôt de l'environnement. Si le système d'exploitation met à votre disposition une librairie d'entrées / sorties asynchrones, alors vous le retrouvez au niveau d'un langage quel qu'il soit.
Il faut remarquer une chose qui est importante, c'est qu'un programme monothread qui exécute une requête asynchrone n'est pas bloqué pendant l'exécution de la requête 🤩. Ca veut dire que ce programme va continuer son exécution et en particulier va continuer à être capable de traiter les événements clavier ou souris venant d'un éventuel opérateur. Par contre, un programme monothread qui exécute une requête synchrone est bloqué pendant l'exécution de la requête 😴. Les événements clavier ou souris ne sont pas traités. Le navigateur est figé.
Par exemple, sur un navigateur, un script qui fait une requête AJAX depuis JavaScript. Cette requête est non bloquante. Le moteur JavaScript continue son exécution et l'internaute qui se trouve devant le navigateur n'est pas devant une application bloquée. Autre exemple en JavaScript, sous Node.js, vous pouvez faire un appel système de manière asynchrone par exemple pour lire ou écrire dans un fichier. Ici, c'est une librairie (libuv) qui fournit le service. Ca vous évite d'être obligé de coder une application multithread ou multiprocessus.
#2 Comment ça se passe au niveau de l'exécution du code ?
Maintenant, l'objectif, c'est de faire une requête asynchrone puis une requête synchrone. Pour cela, je vais utiliser l'objet JavaScript XMLHttpRequest
. Je vais vous montrer ce qui se passe en cours d'exécution lorsque le navigateur n'est pas bloqué (asynchrone) ou bloqué (synchrone).
Pour cela, j'ai besoin des trois fichiers que vous pouvez voir ci-dessous. Les trois fichiers sont sur mon serveur.
- Le premier fichier
req-asynchrone.html
est chargé dans le navigateur et fait une requêteasynchrone
vers le scriptprocess.php
qui lui reste sur le serveur et lui répond. - Le deuxième fichier
req-synchrone.html
fait une requête synchrone vers le même scriptprocess.php
. - Le script
process.php
répond au deux requêtes en faisant unecho
deOK
, mais après un délai de 20 secondes.
Le code du script process.php
est ci-dessous.
Le code du fichier req-asynchrone.html
qui va envoyer la requête asynchrone se trouve ci-dessous.
Ci-dessous, vous pouvez constater que le console.log('Début')
de la ligne 8 s'exécute logiquement en premier. Puis, attention, c'est au tour du console.log('Fin')
de la ligne 24 . Puis, on remonte à la ligne 17 pour exécuter le console.log('Traitement...')
lorsque la réponse est disponible, c'est-à-dire 20 secondes après l'envoi de la requête.
Pendant que j'attends la réponse, il est important de voir, que je continue à avoir accès à la console. Je peux faire un console.log
de Bonjour
. De la même manière, j'ai accès à la page web. S'il y avait des boutons, je pourrais cliquer dessus. S'il y avait des formulaires, je pourrais les remplir. En d'autres termes, le navigateur continue de traiter les événements clavier et souris.
Ci-dessous, je fais une petite modification du code pour demander une gestion synchrone de la requête. Je sauvegarde dans un nouveau fichier sous le nom de req-synchrone.html
. J'ajoute un booléen à false
au niveau de l'appel du xhr.open
, c'est tout. C'est la seule différence avec le code précédent.
Ci-dessous, vous pouvez constater de nouveau que le console.log('Début')
de la ligne 8 s'exécute logiquement en premier, mais cette fois, il faut attendre 20 secondes pour voir s'afficher le console.log('Traitement...')
de la ligne 13. Ici le code est bloqué sur le xhr.send
et pendant ce temps, il est impossible d'exécuter quoi que ce soit à la console ou dans la page web. Le navigateur ou l'OS met les événements souris ou clavier en pile, mais le moteur JavaScript ne les traite pas. Votre appli est figée. Ensuite, c'est au tour du console.log('Fin')
de la ligne 19 de s'afficher. Au passage, le navigateur nous affiche un warning pour nous rappeler que ce mode de fonctionnement est déprécié. Je l'utilise ici pour la démo, mais ce n'est pas une bonne pratique de procéder ainsi.
Alors, pourquoi ce changement de comportement ? Eh bien, parce qu'ici l'attente de la réponse est bloquante alors que précédemment, elle était non bloquante. C'est la différence entre synchrone et asynchrone ! 😇