Maison  >  Article  >  interface Web  >  Explication détaillée du mécanisme d'exécution du moteur js

Explication détaillée du mécanisme d'exécution du moteur js

小云云
小云云original
2018-03-31 17:11:112902parcourir


Cet article partage principalement avec vous l'explication détaillée du mécanisme d'exécution du moteur js, en espérant aider tout le monde.

Tout d'abord, veuillez garder 2 points à l'esprit :

  • js est un langage monothread

  • L'événement la boucle en js est le mécanisme d'exécution de js. Une compréhension approfondie de l'exécution de js équivaut à une compréhension approfondie de la boucle d'événements dans js

Pourquoi js est-il monothread ?

js a été conçu à l'origine pour être utilisé dans les navigateurs, alors imaginez si js dans le navigateur était multithread.

Description du scénario :

Alors maintenant, il y a 2 processus, process1 et process2 Puisqu'il s'agit d'un js multi-processus, ils opèrent sur le même dom en même temps. , et Process2 a édité le DOM et a émis deux commandes contradictoires en même temps. Comment le navigateur doit-il les exécuter ?

En y réfléchissant de cette façon, il devrait être facile de comprendre pourquoi js est conçu pour être monothread.

Pourquoi js a-t-il besoin d'un mode asynchrone ?

Description de la scène ;

S'il n'y a pas d'asynchrone dans js, il ne peut être exécuté que de haut en bas. Si le temps d'analyse de la ligne précédente est très long, le code suivant sera. bloqué. Pour les utilisateurs, le blocage signifie « bloqué », ce qui conduit à une mauvaise expérience utilisateur.

Donc, il y a une exécution asynchrone en js.

Comment un seul thread réalise-t-il une implémentation asynchrone ?

Puisque JS est monothread et ne peut être exécuté que sur un seul thread, comment réaliser une implémentation asynchrone

C'est via la boucle d'événement (boucle d'événement), et nous comprenons la fonction de ? js Mécanisme d'exécution.

Boucle d'événement (1) en js

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);// 输出 1 3 2

C'est-à-dire que la fonction dans setTimeout n'est pas exécutée immédiatement, mais est retardée pendant un certain temps et n'est exécutée qu'après certaines conditions sont remplies. Ce type de code exécuté est appelé code asynchrone.

Donc, ici nous connaissons d'abord une méthode de classification en JS, qui consiste à diviser les tâches en : tâches synchrones et tâches asynchrones

Selon cette méthode de classification, le mécanisme d'exécution de js est :

  • Déterminez d'abord si le js est synchrone ou asynchrone S'il est synchrone, il entrera dans le thread principal, s'il est asynchrone, il entrera dans la table des événements

  • Les tâches asynchrones sont dans l'événement La fonction est enregistrée dans le tableau Lorsque la condition de déclenchement est remplie, elle est poussée dans la file d'attente des événements

  • La tâche de synchronisation entre. le thread principal et est exécuté jusqu'à ce que le thread principal soit inactif. Ensuite, il va dans la file d'attente des événements pour vérifier s'il existe des tâches asynchrones exécutables, et si c'est le cas, elles sont poussées vers le thread principal.

L'exécution de la boucle en trois étapes ci-dessus est la boucle d'événements

Donc, pour l'exemple ci-dessus, pouvez-vous décrire leur ordre d'exécution ?

console.log(1); // 同步任务,放入主线程中setTimeout(function() {
  // 异步任务,放到event table中,0秒后被推入到event queue中
  console.log(2);
}, 0);
console.log(3); // 同步任务,放到主线程中// 输出 1 3 2// 当1,3被打印后,主线程去event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里面的函数。

Boucle d'événement (2) en js

Regardez l'exemple suivant :

setTimeout(function() {
  console.log("定时器开始");
}, 0);new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  console.log("执行then函数拉");
});
console.log("代码执行结束");

Utilisez le mécanisme d'exécution js résumé précédemment pour analyser :

setTimeout 是异步任务,放在 event table中new promise是同步任务,被放到主线程中,直接打印console.log('马上执行for循环了');

.then里面的是异步任务,被放到event table中

console.log('代码执行结束') 是同步代码,被放在主线程中,直接执行。

Donc, le résultat est [exécuter la boucle for immédiatement - l'exécution du code se termine - le minuteur démarre - la fonction then est exécutée] ?

Après l'avoir exécuté moi-même, le résultat n'est pas comme ceci, mais c'est [exécuter la boucle for immédiatement—l'exécution du code se termine—exécuter la fonction then—le minuteur démarre]

Donc, est-ce l'ordre d'exécution des tâches asynchrones, pas l'ordre avant et après , mais d'autres réglementations ? En fait, selon la méthode de division asynchrone et synchrone, ce n'est pas précis

mais la méthode de division précise est :

  • macro-tâche (macro-tâche) : script de code global, setTimeout , setInterval

  • micro-tâche (micro-tâche) : Promesse, processus, nextTick

Explication détaillée du mécanisme dexécution du moteur js

Suivez ceci Une méthode de classification, le mécanisme d'exécution de js est :

  • Exécuter une macro-tâche si une micro-tâche est rencontrée pendant le processus, mettez. dans la file d'attente des événements de la micro-tâche

  • Une fois l'exécution de la macro-tâche en cours terminée, la file d'attente des événements de la micro-tâche sera vérifiée et toutes les micro-tâches qu'elle contient seront exécutés en séquence.

Répétez les 2 étapes ci-dessus, combinées avec event loop(1) event loop(2), pour obtenir un mécanisme d'exécution JS plus précis.

Selon le mécanisme de tout à l'heure, analysez l'exemple 2 :

// 首先执行script下的宏任务,遇到setTimeout,将其放在宏任务队列中setTimeout(function() {
  console.log("定时器开始");
}, 0);// 遇到new promise直接执行new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  // .then方法,是微任务,放在微任务队列中
  console.log("执行then函数拉");
});
console.log("代码执行结束");// 宏任务执行完毕,查看本轮的微任务,返现有一个then方法。再去执行宏任务队列中的函数。

Parlez de setTimeout

Que signifie ce code setTimeout On dit généralement : il sera exécuté ? après 3 secondes La fonction dans setTimeout

setTimeout(function() {
  console.log("执行了");
}, 3000);

Mais ce n'est pas rigoureux. L'explication précise est la suivante : après 3 secondes, la fonction dans setTimeout sera poussée dans la file d'attente des événements et la file d'attente des événements (file d'attente des événements). ) La tâche ne sera exécutée que lorsque le thread principal est inactif.

Donc seulement si (1) 3 secondes plus tard (2) le thread principal est inactif et que les deux sont remplis, la fonction sera exécutée après 3 secondes

Si le thread principal exécute beaucoup de contenu, Si le temps d'exécution dépasse 3 secondes, par exemple, si elle est exécutée pendant 10 secondes, alors cette fonction ne peut être exécutée qu'après 10 secondes

Compréhension approfondie du mécanisme d'exécution du moteur js

Tout d'abord, veuillez garder 2 points à l'esprit :

  • js est un langage monothread

  • La boucle d'événements en js est le mécanisme d'exécution de js. Une compréhension approfondie de l'exécution de js équivaut à une compréhension approfondie de la boucle d'événements dans js

Pourquoi js est-il monothread ?

js a été conçu à l'origine pour être utilisé dans les navigateurs, alors imaginez si js dans le navigateur était multithread.

Description de la scène :

那么现在有 2 个进程,process1 process2,由于是多进程的 js,所以他们对同一个 dom,同时进行操作,process1 删除了该 dom,而 process2 编辑了该 dom,同时下达 2 个矛盾的命令,浏览器究竟该如何执行呢?

这样想,js 为什么被设计成单线程应该就容易理解了吧。

js 为什么需要异步?

场景描述;

如果 js 中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。对于用户而言,阻塞就意味着‘卡死’,这样就导致了很差的用户体验。

所以,js 中存在异步执行。

单线程又是如何实现异步的呢?

既然 JS 是单线程的,只能在一条线程上执行,又是如何实现的异步呢?

是通过的事件循环(event loop), 就理解了 js 的执行机制。

js 中的 event loop(1)

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);// 输出 1 3 2

也就是说,setTimeout 里的函数并没有立即执行,而是延迟了一段时间,满足一定条件后,才去执行的,这类代码,我们叫异步代码。

所以,这里我们首先知道了 JS 里的一种分类方式,就是将任务分为: 同步任务和异步任务

按这种分类方式,js 的执行机制就是:

  • 首先判断 js 是同步的还是异步的,同步的就进入主线程,异步就进入 event table

  • 异步任务在 event table 中注册函数,当满足触发条件后,被推入 event queue

  • 同步任务进入主线程后一直执行,直到主线程空闲,才会去 event queue 中查看是否有可执行的异步任务,若果有就推入到主线程中。

以上三步循环执行,就是 event loop

所以上述例子,你是否可以描述他们的执行顺序了?

console.log(1); // 同步任务,放入主线程中setTimeout(function() {
  // 异步任务,放到event table中,0秒后被推入到event queue中
  console.log(2);
}, 0);
console.log(3); // 同步任务,放到主线程中// 输出 1 3 2// 当1,3被打印后,主线程去event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里面的函数。

js 中的 event loop(2)

再看下一个例子:

setTimeout(function() {
  console.log("定时器开始");
}, 0);new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  console.log("执行then函数拉");
});
console.log("代码执行结束");

用之前总结的 js 执行机制去分析:

setTimeout 是异步任务,放在 event table中new promise是同步任务,被放到主线程中,直接打印console.log('马上执行for循环了');

.then里面的是异步任务,被放到event table中

console.log('代码执行结束') 是同步代码,被放在主线程中,直接执行。

所以,结果是 【马上执行 for 循环啦 — 代码执行结束 — 定时器开始啦 — 执行 then 函数啦】吗?

亲自执行后,结果居然不是这样,而是【马上执行 for 循环啦 — 代码执行结束 — 执行 then 函数啦 — 定时器开始啦】

那么,难道是异步任务的执行顺序,不是前后顺序,而是另有规定? 事实上,按照异步和同步的划分方式,并不准确

而准确的划分方式是:

  • macro-task(宏任务): 整体代码 script, setTimeout,setInterval

  • micro-task(微任务): Promise,process,nextTick

Explication détaillée du mécanisme dexécution du moteur js

按照这种分类方式,js 的执行机制就是:

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的 event queue 中

  • 当前宏任务执行完成后,会常看微任务的 event queue ,并将里面全部的微任务依次执行完。

重复以上 2 步骤,结合 event loop(1) event loop(2) ,就是更为准确的 JS 执行机制了。

按照刚才的机制,分析例 2:

// 首先执行script下的宏任务,遇到setTimeout,将其放在宏任务队列中setTimeout(function() {
  console.log("定时器开始");
}, 0);// 遇到new promise直接执行new promise(function(resolve) {
  console.log("马上执行for循环了");
}).then(function(resolve) {
  // .then方法,是微任务,放在微任务队列中
  console.log("执行then函数拉");
});
console.log("代码执行结束");// 宏任务执行完毕,查看本轮的微任务,返现有一个then方法。再去执行宏任务队列中的函数。

谈谈 setTimeout

这段 setTimeout 代码什么意思? 我们一般说: 3 秒后,会执行 setTimeout 里的那个函数

setTimeout(function() {
  console.log("执行了");
}, 3000);

但是这种说并不严谨,准确的解释是: 3 秒后,setTimeout 里的函数被会推入 event queue,而 event queue(事件队列)里的任务,只有在主线程空闲时才会执行。

所以只有满足 (1)3 秒后 (2)主线程空闲,同时满足时,才会 3 秒后执行该函数

如果主线程执行内容很多,执行时间超过 3 秒,比如执行了 10 秒,那么这个函数只能 10 秒后执行了

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