J'ai eu l'impression que JavaScript était toujours asynchrone. Cependant, j'ai appris qu'il y a des situations où ce n'est pas le cas (c'est-à-dire les manipulations DOM). Y a-t-il une bonne référence quelque part sur le moment où il sera synchrone et quand il sera asynchrone? JQuery affecte-t-il cela du tout?
javascript
jquery
Brian
la source
la source
Réponses:
JavaScript est toujours synchrone et monothread. Si vous exécutez un bloc de code JavaScript sur une page, aucun autre JavaScript de cette page ne sera actuellement exécuté.
JavaScript est uniquement asynchrone dans le sens où il peut effectuer, par exemple, des appels Ajax. L'appel Ajax cessera de s'exécuter et tout autre code pourra s'exécuter jusqu'à ce que l'appel revienne (avec succès ou non), moment auquel le rappel s'exécutera de manière synchrone. Aucun autre code ne sera exécuté à ce stade. Il n'interrompra aucun autre code en cours d'exécution.
Les minuteries JavaScript fonctionnent avec ce même type de rappel.
Décrire JavaScript comme asynchrone est peut-être trompeur. Il est plus précis de dire que JavaScript est synchrone et monothread avec divers mécanismes de rappel.
jQuery a une option sur les appels Ajax pour les faire de manière synchrone (avec l'
async: false
option). Les débutants pourraient être tentés de l'utiliser incorrectement car cela permet un modèle de programmation plus traditionnel auquel on pourrait être plus habitué. La raison pour laquelle cela pose problème est que cette option bloquera tout le JavaScript sur la page jusqu'à ce qu'elle se termine, y compris tous les gestionnaires d'événements et les minuteurs.la source
JavaScript est monothread et possède un modèle d'exécution synchrone. Un thread unique signifie qu'une seule commande est exécutée à la fois. Synchrone signifie une à la fois, c'est-à-dire qu'une ligne de code est exécutée à la fois afin que le code apparaisse. Donc, en JavaScript, une chose se produit à la fois.
Contexte d'exécution
Le moteur JavaScript interagit avec les autres moteurs du navigateur. Dans la pile d'exécution JavaScript, il y a un contexte global en bas, puis lorsque nous invoquons des fonctions, le moteur JavaScript crée de nouveaux contextes d'exécution pour les fonctions respectives. Lorsque la fonction appelée quitte son contexte d'exécution est extrait de la pile, puis le contexte d'exécution suivant est extrait et ainsi de suite ...
Par exemple
Dans le code ci-dessus, un contexte d'exécution global sera créé et dans ce contexte
var one
sera stocké et sa valeur sera 1 ... lorsque l'invocation xyz () est appelée, un nouveau contexte d'exécution sera créé et si nous avions défini une variable dans la fonction xyz, ces variables seraient stockées dans le contexte d'exécution de xyz (). Dans la fonction xyz, nous invoquons abc () puis le contexte d'exécution abc () est créé et placé sur la pile d'exécution ... Maintenant, lorsque abc () termine, son contexte est extrait de la pile, puis le contexte xyz () est extrait de pile et puis le contexte global sera sauté ...Maintenant sur les rappels asynchrones; asynchrone signifie plus d'un à la fois.
Tout comme la pile d'exécution, il y a la file d'attente d'événements . Lorsque nous voulons être informés d'un événement dans le moteur JavaScript, nous pouvons l'écouter et cet événement est placé dans la file d'attente. Par exemple, un événement de demande Ajax ou un événement de demande HTTP.
Chaque fois que la pile d'exécution est vide, comme illustré dans l'exemple de code ci-dessus, le moteur JavaScript examine périodiquement la file d'attente des événements et voit s'il y a un événement à notifier. Par exemple, dans la file d'attente, il y avait deux événements, une demande ajax et une demande HTTP. Il cherche également à voir s'il existe une fonction qui doit être exécutée sur ce déclencheur d'événement ... Le moteur JavaScript est donc informé de l'événement et connaît la fonction respective à exécuter sur cet événement ... Le moteur JavaScript appelle donc le fonction de gestionnaire, dans le cas d'exemple, par exemple AjaxHandler () sera invoqué et comme toujours quand une fonction est invoquée son contexte d'exécution est placé sur le contexte d'exécution et maintenant l'exécution de la fonction se termine et la requête ajax d'événement est également supprimée de la file d'attente d'événements ... Une fois AjaxHandler () terminé, la pile d'exécution est vide, de sorte que le moteur examine à nouveau la file d'attente d'événements et exécute la fonction de gestionnaire d'événements de la requête HTTP qui se trouvait ensuite dans la file d'attente. Il est important de se rappeler que la file d'attente d'événements n'est traitée que lorsque la pile d'exécution est vide.
Par exemple, voir le code ci-dessous expliquant la pile d'exécution et la gestion de la file d'attente d'événements par le moteur Javascript.
Et
Maintenant, lancez la page Web et cliquez sur la page, et voyez la sortie sur la console. La sortie sera
Le moteur JavaScript exécute le code de manière synchrone comme expliqué dans la partie contexte d'exécution, le navigateur place les choses de manière asynchrone dans la file d'attente des événements. Ainsi, les fonctions qui prennent très longtemps à s'achever peuvent interrompre la gestion des événements. Les choses qui se passent dans un navigateur comme les événements sont gérées de cette façon par JavaScript, s'il y a un écouteur censé s'exécuter, le moteur l'exécutera lorsque la pile d'exécution sera vide. Et les événements sont traités dans l'ordre où ils se produisent, donc la partie asynchrone concerne ce qui se passe en dehors du moteur, c'est-à-dire ce que le moteur doit faire lorsque ces événements extérieurs se produisent.
JavaScript est donc toujours synchrone.
la source
JavaScript est monothread et vous travaillez tout le temps sur une exécution normale de flux de code synchrone.
De bons exemples du comportement asynchrone que JavaScript peut avoir sont les événements (interaction de l'utilisateur, résultats des requêtes Ajax, etc.) et les temporisateurs, essentiellement des actions qui peuvent se produire à tout moment.
Je vous recommande de jeter un œil à l'article suivant:
Cet article vous aidera à comprendre la nature monothread de JavaScript et comment les minuteurs fonctionnent en interne et comment fonctionne l'exécution asynchrone de JavaScript.
la source
Pour quelqu'un qui comprend vraiment comment fonctionne JS, cette question peut sembler fausse, mais la plupart des gens qui utilisent JS n'ont pas un niveau de compréhension aussi profond (et n'en ont pas nécessairement besoin) et pour eux, c'est un point assez déroutant, je le ferai essayez de répondre de ce point de vue.
JS est synchrone dans la façon dont son code est exécuté. chaque ligne ne s'exécute qu'après la ligne avant qu'elle ne soit terminée et si cette ligne appelle une fonction après cela, ect ...
Le principal point de confusion provient du fait que votre navigateur est en mesure de dire à JS d'exécuter plus de code à tout moment (simmlar à la façon dont vous pouvez excuter plus de code JS sur une page de la console). Par exemple, JS a des fonctions de rappel qui ont pour but de permettre à JS de se comporter de manière asynchrone afin que d'autres parties de JS puissent s'exécuter en attendant qu'une fonction JS qui a été exécutée (IE un
GET
appel) renvoie une réponse, JS continuera à s'exécuter jusqu'à le navigateur a une réponse à ce stade, la boucle d'événements (navigateur) exécutera le code JS qui appelle la fonction de rappel.Étant donné que la boucle d'événements (navigateur) peut entrer plus de JS à exécuter à tout moment dans ce sens, JS est asynchrone (les principaux éléments qui amèneront un navigateur à entrer du code JS sont les délais d'attente, les rappels et les événements)
J'espère que cela est suffisamment clair pour être utile à quelqu'un.
la source
Définition
Le terme «asynchrone» peut être utilisé dans des sens légèrement différents, ce qui donne lieu à des réponses apparemment contradictoires, alors qu'elles ne le sont pas réellement. Wikipédia sur Asynchrony a cette définition:
le code non JavaScript peut mettre en file d'attente de tels événements "extérieurs" à certaines des files d'attente d'événements de JavaScript. Mais c'est aussi loin que ça va.
Pas de préemption
Il n'y a pas externe interruption de l'exécution du code JavaScript afin d'exécuter un autre code JavaScript dans votre script. Des morceaux de JavaScript sont exécutés les uns après les autres, et l'ordre est déterminé par l'ordre des événements dans chaque file d'attente d'événements et la priorité de ces files d'attente.
Par exemple, vous pouvez être absolument sûr qu'aucun autre JavaScript (dans le même script) ne s'exécutera jamais pendant l'exécution du morceau de code suivant:
En d'autres termes, il n'y a pas de préemption en JavaScript. Quoi qu'il puisse y avoir dans les files d'attente d'événements, le traitement de ces événements devra attendre que ce morceau de code soit terminé. La spécification EcmaScript dit dans section 8.4 Travaux et files d'attente de travaux :
Exemples d'asynchronie
Comme d'autres l'ont déjà écrit, il existe plusieurs situations où l'asynchronie entre en jeu dans JavaScript, et cela implique toujours une file d'attente d'événements, qui ne peut entraîner l'exécution de JavaScript que lorsqu'il n'y a pas d'autre code JavaScript en cours d'exécution:
setTimeout()
: l'agent (par exemple le navigateur) mettra un événement dans une file d'attente d'événements une fois le délai expiré. La surveillance de l'heure et le placement de l'événement dans la file d'attente se fait par du code non JavaScript, et vous pouvez donc imaginer que cela se produit en parallèle avec l'exécution potentielle de certains codes JavaScript. Mais le rappel fourni àsetTimeout
ne peut s'exécuter que lorsque le code JavaScript en cours d'exécution s'est terminé et que la file d'attente d'événements appropriée est en cours de lecture.fetch()
: l'agent utilisera les fonctions du système d'exploitation pour effectuer une requête HTTP et surveiller toute réponse entrante. Encore une fois, cette tâche non JavaScript peut s'exécuter en parallèle avec du code JavaScript toujours en cours d'exécution. Mais la procédure de résolution de promesse, qui résoudra la promesse retournée parfetch()
, ne peut être exécutée que lorsque le JavaScript en cours d'exécution est terminé.requestAnimationFrame()
: le moteur de rendu du navigateur (non JavaScript) placera un événement dans la file d'attente JavaScript lorsqu'il sera prêt à effectuer une opération de peinture. Lorsque l'événement JavaScript est traité, la fonction de rappel est exécutée.queueMicrotask()
: place immédiatement un événement dans la file d'attente des microtâches. Le rappel sera exécuté lorsque la pile d'appels est vide et que cet événement est consommé.Il existe de nombreux autres exemples, mais toutes ces fonctions sont fournies par l'environnement hôte, et non par le noyau EcmaScript. Avec le noyau EcmaScript, vous pouvez synchroniser un événement dans une file d'attente de travaux Promise avec
Promise.resolve()
.Constructions de langage
EcmaScript fournit plusieurs constructions de langage pour soutenir le modèle de asynchronisme, tels que
yield
,async
,await
. Mais ne vous y trompez pas: aucun code JavaScript ne sera interrompu par un événement externe. L '"interruption" quiyield
etawait
semble fournir n'est qu'un moyen contrôlé et prédéfini de revenir d'un appel de fonction et de restaurer son contexte d'exécution ultérieurement, soit par le code JS (dans le cas deyield
), soit par la file d'attente des événements (dans le cas deawait
).Gestion des événements DOM
Lorsque le code JavaScript accède à l'API DOM, cela peut dans certains cas faire déclencher une ou plusieurs notifications synchrones par l'API DOM. Et si votre code a un gestionnaire d'événements qui l'écoute, il sera appelé.
Cela peut apparaître comme une concurrence préemptive, mais ce n'est pas le cas: une fois que votre ou vos gestionnaires d'événements retourneront, l'API DOM finira également par revenir et le code JavaScript d'origine continuera.
Dans d'autres cas, l'API DOM enverra simplement un événement dans la file d'attente d'événements appropriée, et JavaScript le récupérera une fois la pile d'appels vide.
Voir les événements synchrones et asynchrones
la source
Est synchrone dans tous les cas.
Exemple de blocage de thread avec
Promises
:La sortie sera:
la source