Maison >interface Web >js tutoriel >Explication détaillée du mécanisme de fonctionnement JavaScript et analyse conceptuelle

Explication détaillée du mécanisme de fonctionnement JavaScript et analyse conceptuelle

零到壹度
零到壹度original
2018-04-09 14:53:312119parcourir

J'ai une très vague impression de JavaScript. Il est monothread et asynchrone. Cet article parle principalement du fonctionnement de JavaScript. Mais avant cela, comprenons d'abord ces concepts (apprendre maintenant et vendre maintenant) .

Concepts de base

Threads et processus

Le processus est l'unité d'allocation et de planification des ressources du système. Un programme en cours d’exécution correspond à un processus. Un processus comprend les programmes en cours d'exécution ainsi que les ressources mémoire et système utilisées par les programmes. S'il s'agit d'un processeur monocœur, un seul processus s'exécute en même temps. Cependant, un processeur monocœur peut également exécuter plusieurs tâches en même temps. Par exemple, vous pouvez écouter les chansons recommandées quotidiennement par NetEase Cloud Music tout en écrivant un article de blog sur NetEase Youdao Cloud Notes. Cela compte pour deux processus (multi-processus). Le mécanisme en cours consiste à lire des chansons pendant un certain temps et à répondre à votre frappe pendant un certain temps. Cependant, comme la vitesse de commutation du processeur est très rapide, vous ne pouvez pas le ressentir du tout. de sorte que vous pensez que ces deux processus s’exécutent en même temps. Les ressources sont isolées entre les processus.

Qu'est-ce qu'un fil de discussion ? Un thread est l'exécuteur d'un processus. Un processus démarrera au moins un thread (le thread principal) et il peut également démarrer plusieurs threads. Par exemple, NetEase Cloud Music lit l'audio et affiche les paroles en même temps. L'opération multi-processus est en fait exécutée via des threads dans le processus. Les threads sous un processus partagent des ressources. Lorsque plusieurs threads exploitent la même ressource en même temps, un conflit de ressources se produit. C'est une autre question.

Parallélisme et concurrence

Le parallélisme fait référence à l'état d'exécution d'un programme, où plusieurs éléments sont traités en parallèle en même temps. Puisqu’un thread ne peut gérer qu’une seule chose à la fois, le parallélisme nécessite que plusieurs threads effectuent plusieurs choses en même temps.

La concurrence fait référence à la structure de conception d'un programme afin que plusieurs éléments puissent être traités alternativement en même temps. Le fait est qu’une seule chose s’exécute à la fois. Par exemple, un processeur monocœur peut réaliser le processus d’exécution simultanée de plusieurs tâches.

Synchronisation et asynchrone

La synchronisation et asynchrone font référence au comportement du programme. Synchrone (Synchronous) signifie que lorsque le programme effectue un appel, il attend que le résultat soit renvoyé. Il ne reviendra que lorsqu'il n'y aura aucun résultat. En d’autres termes, la synchronisation se produit lorsque l’appelant attend activement le processus appelant.

Asynchrone signifie revenir immédiatement après avoir émis un appel, mais le résultat ne sera pas renvoyé immédiatement. L'appelant n'a pas à attendre activement lorsque l'appelé obtient le résultat, il en informera activement l'appelant.

Par exemple, rendez-vous dans un magasin de thé au lait pour acheter des boissons. La synchronisation signifie qu'un client énonce un besoin (demande) puis attend que le serveur prépare la boisson. Le client part après avoir reçu la boisson qu'il a commandée, puis le client suivant continue de répéter le processus ci-dessus. Asynchrone signifie que les clients font la queue pour commander en premier, et après la commande, ils mettent la commande de côté. Le serveur appellera leur numéro lorsqu'il sera prêt. Lorsqu'il sera appelé, vous irez simplement la chercher.

Les threads ne sont donc pas directement liés à la synchronisation et à l'asynchronie, et un seul thread peut également réaliser une implémentation asynchrone. Quant à la méthode de mise en œuvre, elle sera discutée en détail ci-dessous.

Blocage et non-blocage

Le blocage et le non-blocage font référence à l'état d'attente. Le blocage signifie que le thread est "suspendu" pendant que l'appel est en attente (les ressources CPU sont allouées ailleurs).

Non bloquant (Non bloquant) signifie que les ressources CPU du processus en attente sont toujours dans le thread et que le thread peut également faire d'autres choses.

Prenons l'exemple de faire la queue pour acheter des boissons tout à l'heure. Le blocage signifie que vous ne pouvez rien faire en attendant. Le non-blocage signifie que vous pouvez faire autre chose en attendant.

Ainsi, la synchronisation peut être bloquante ou non bloquante, et l'asynchrone peut être bloquante ou non bloquante.

JS monothread

Après avoir grossièrement compris les concepts ci-dessus, vous saurez qu'il n'y a pas de contradiction entre le monothreading et l'asynchrone. Alors, comment JS est-il exécuté ? JS est en fait un langage, qu'il soit monothread ou multithread dépend de l'environnement d'exploitation spécifique. JS est généralement exécuté dans le navigateur, analysé et exécuté par le moteur JS. Regardons de plus près le navigateur.

Navigateur

Les navigateurs les plus populaires actuellement sont : Chrome, IE, Safari, FireFox, Opera. Le cœur du navigateur est multithread. Un navigateur se compose généralement des threads résidents suivants :

  • Fil du moteur de rendu : Comme son nom l'indique, ce fil est responsable du rendu de la page

  • Thread du moteur JS : responsable de l'analyse et de l'exécution de JS

  • Thread de déclenchement de synchronisation : traitement des événements de synchronisation, tels que setTimeout, setInterval

  • Thread de déclenchement d'événements : Traitement des événements DOM

  • Fil de requêtes http asynchrones : Traitement des requêtes http

Il est à noter que le thread de rendu et le JS le thread moteur ne peut pas être traité en même temps. Lorsque le thread de rendu exécute des tâches, le thread du moteur JS sera suspendu. Étant donné que JS peut manipuler le DOM, si JS traite le DOM pendant le rendu, le navigateur peut être perdu.

Moteur JS

Habituellement, lorsqu'on parle de navigateurs, on parlera de deux moteurs : le moteur de rendu et le moteur JS. Le moteur de rendu indique comment rendre la page. Chrome/Safari/Opera utilise le moteur Webkit, IE utilise le moteur Trident et FireFox utilise le moteur Gecko. Différents moteurs implémentent le même style de manière incohérente, ce qui conduit au problème de compatibilité des styles de navigateur qui est souvent critiqué. Nous n’en discuterons pas en détail ici.

Le moteur JS peut être considéré comme une machine virtuelle JS, responsable de l'analyse et de l'exécution du code JS. Cela comprend généralement les étapes suivantes :

  • Analyse lexicale : décomposer le code source en segments de mots significatifs

  • Analyse syntaxique : utiliser un analyseur de syntaxe Parse la segmentation des mots dans un arbre syntaxique

  • Génération de code : Générer du code que la machine peut exécuter

  • Exécution de code

Les moteurs JS des différents navigateurs sont également différents. Chrome utilise V8, FireFox utilise SpiderMonkey, Safari utilise JavaScriptCore et IE utilise Chakra.

Pour en revenir à l'affirmation selon laquelle JS est monothread, essentiellement, le navigateur n'ouvre qu'un seul thread de moteur JS pour analyser et exécuter JS pendant l'exécution. Alors pourquoi un seul moteur ? S'il y a deux threads qui exploitent le DOM en même temps, le navigateur sera-t-il à nouveau perdu ? !

Mécanisme d'exécution de JS

Après avoir tant parlé, nous voulons enfin parler de l'ensemble du processus d'exécution de JS.

Exécution synchrone

Voyons d'abord comment le processus d'exécution synchrone JS est réalisé ? Cela implique un concept très important : le contexte d’exécution. L'une de mes traductions, Deep Learning JavaScript Closures, explique ce concept en détail.

Le contexte d'exécution enregistre l'environnement lorsque le code est en cours d'exécution. Il existe un contexte d'exécution en vigueur dans l'état d'exécution actuel. Alors, qu’est-ce qui est exactement enregistré dans le contexte d’exécution ? Il existe probablement un environnement lexical, un environnement variable, etc. Pour donner un exemple simple :

var x = 10;

function foo(){
    var y=20;
    function bar(){
        var z=15; 
    }
    bar();
}

foo();

Lorsque le code est exécuté, il entre d'abord dans le contexte global. Ensuite, lorsque foo() est exécuté, le contexte foo est entré. Bien sûr, le contexte global est toujours là à ce moment-là. Lorsque bar() est exécuté, le contexte de la barre est à nouveau saisi. Après l'exécution bar(), revenez au contexte foo. Après avoir exécuté foo(), revenez au contexte global. Par conséquent, le contexte d'exécution du processus d'exécution formera une pile d'appels (Call stack), premier entré, dernier sorti.

// 进栈
                                                          3 bar Context
    =>                      =>   2 foo Context     =>     2 foo Context
        1 global Context         1 global Context         1 global Context

// 出栈
3 bar Context
2 foo Context     =>   2 foo Context     =>                        =>
1 global Context       1 global Context         1 global Context

Pendant l'exécution de JS, il y a et il n'y a qu'un seul contexte d'exécution en vigueur. Parce que JS est monothread, il ne peut faire qu’une seule chose à la fois.

Les processus ci-dessus sont tous exécutés de manière synchrone.

Exécution asynchrone - boucle d'événements

Voyons quels événements asynchrones natifs existent dans JS :

  • setTimeout

  • setInterval

  • Écouteur d'événement

  • Demande Ajax

  • etc. 🎜>

  • L'effet asynchrone de JS bénéficie de l'environnement d'exécution du navigateur. En fait, le navigateur ouvre un autre thread pour gérer ces événements de nomenclature. Exemple :

Selon l'analyse de la section précédente, entrez d'abord le contexte global, exécutez vers
function foo(){
    console.log(1);
}

function bar(){
    console.log(2);
}

foo();

setTimeout(function cb(){
    console.log(3);
});

bar();
et entrez dans l'environnement de contexte foo ; exécutez

, la console affiche 1 ; l'environnement de contexte foo est sorti de la pile, exécuté sur foo() et remis au thread de traitement planifié du navigateur console.log(1) setTimeout, exécuté sur et entrez le contexte de la barre exécuter , et la console affiche 2 ; le contexte foo apparaît ; Attendez que le bar() thread du navigateur console.log(2) termine l'exécution de et renvoie la fonction de rappel à la file d'attente des tâches setTimeout actuelle cb() ; la pile s'avère vide, le moteur JS du navigateur exécutera une boucle et retirera la tête de la file d'attente des événements vers la pile d'exécution JS exécuter pour entrer dans l'environnement de contexte cb exécuter  ; et la console affichera 3 ; la file d'attente des événements est vide et le contexte global sera retiré de la pile. cb()console.log(3)Ce qui précède est le mécanisme de boucle d'événements du moteur JS, qui est un mécanisme permettant de réaliser une implémentation asynchrone. Il s'agit principalement du

thread du navigateur

, de la file d'attente des tâches et du moteur JS. Par conséquent, nous pouvons voir que la requête asynchrone de JS s'appuie sur le navigateur de son environnement d'exécution pour traiter et renvoyer le résultat. De plus, cela explique aussi pourquoi le de ces fonctions de rappel pointe vers , car ces codes asynchrones sont exécutés dans le contexte global. thiswindowPostface : Je ne sais pas si j’ai bien compris, et je ne sais pas si je l’ai expliqué clairement ou pas. S'il y a un caractère inapproprié, veuillez le signaler.

Documents de référence :

    JavaScript : Comprendre parfaitement la synchronisation, l'asynchrone et la boucle d'événements (Event Loop)
  • Je me demande toujours la concurrence et le parallélisme ?
  • Processus du navigateur de la communauté IMWeb ? Fil de discussion? C'est idiot, je ne peux pas faire la différence !
  • Analyse approfondie du caractère monothread de Javascript
  • Une brève introduction au monothreading JavaScript et à la boucle d'événements du navigateur
  • AlloyTeam [Tournez-vous vers Javascript Series] Parlons du modèle de boucle d'événements de setTimeout
  • Principes de programmation asynchrone JavaScript par Brother Moustache
  • Ruan Yifeng JavaScript en cours d'exécution Explication détaillée du mécanisme : reparlons d'Event Loop
  • [Commentaire de Pu Ling] Explication détaillée du mécanisme de fonctionnement JavaScript : Parlons d'Event Boucle
  • encore
  • Philip Roberts : Au secours, je suis coincé dans une boucle d'événements.

  • Philip Roberts : C'est quoi la boucle d'événements de toute façon ?

  • jquery中Ajax的异步和同步

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn