Maison > interface Web > js tutoriel > Une analyse approfondie de zone.js dans Angular et de son fonctionnement

Une analyse approfondie de zone.js dans Angular et de son fonctionnement

青灯夜游
Libérer: 2022-02-15 10:11:36
avant
2439 Les gens l'ont consulté

Cet article vous fera découvrir zone.js dans Angular, démontrera les capacités de zone.js à travers un exemple et analysera brièvement le principe de fonctionnement qui le sous-tend. J'espère qu'il sera utile à tout le monde !

Une analyse approfondie de zone.js dans Angular et de son fonctionnement

Vous avez peut-être entendu dire qu'Angular utilise zone.js, mais pourquoi Angular utilise-t-il zone.js et quelles fonctions peut-il fournir ? Aujourd'hui, nous allons écrire un article séparé pour parler de zone.js. Son rôle dans le framework Angular sera discuté dans le prochain article. [Recommandation de didacticiel connexe : "zone.js, 但 Angular 为什么要使用zone.js, 它能够提供哪些功能呢?今天我们单独写一篇文章聊聊zone.js,关于它在 Angular 框架中发挥的作用将在下一篇文章讲述。【相关教程推荐:《angular教程》】

什么是 Zone ? 官方文档是这么解释的:Zone 是一个跨多个异步任务的执行上下文。一句话总结来说,Zone 在拦截或追踪异步任务方面有着特别强大的能力。下面我们将通过一个示例来展示它的能力,并简单剖析一下背后的工作原理。

<button id="b1">Bind Error</button>
<button id="b2">Cause Error</button>
<script>
  function main() {
    b1.addEventListener(&#39;click&#39;, bindSecondButton);
  }
  function bindSecondButton() {
    b2.addEventListener(&#39;click&#39;, throwError);
  }
  function throwError() {
    throw new Error(&#39;aw shucks&#39;);
  }
  main();
</script>
Copier après la connexion

这是一个简单的 HTML 页面。页面加载时会给第一个按钮添加点击事件,其点击事件函数的功能是给第二个按钮添加点击事件,而第二个按钮的点击事件函数功能是抛出一个异常。我们依次点击第一个按钮和第二个按钮,控制台显示如下:

(索引):26 Uncaught Error: aw shucks
    at HTMLButtonElement.throwError ((索引):26:13)
Copier après la connexion

但是如果我们通过zone.js启动运行代码,控制台输出会有什么不同呢,我们先调整启动代码:

  Zone.current.fork(
      {
        name: &#39;error&#39;,
        onHandleError: function (parentZoneDelegate, currentZone, targetZone, error) {
          console.log(error.stack);
        }
      }
    ).fork(Zone.longStackTraceZoneSpec).run(main);
Copier après la connexion

此时控制台输出如下:

Error: aw shucks
    at HTMLButtonElement.throwError ((索引):26:13)
    at ZoneDelegate.invokeTask (zone.js:406:31)
    at Zone.runTask (zone.js:178:47)
    at ZoneTask.invokeTask [as invoke] (zone.js:487:34)
    at invokeTask (zone.js:1600:14)
    at HTMLButtonElement.globalZoneAwareCallback (zone.js:1626:17)
    at ____________________Elapsed_571_ms__At__Mon_Jan_31_2022_20_09_09_GMT_0800_________ (localhost)
    at Object.onScheduleTask (long-stack-trace-zone.js:105:22)
    at ZoneDelegate.scheduleTask (zone.js:386:51)
    at Zone.scheduleTask (zone.js:221:43)
    at Zone.scheduleEventTask (zone.js:247:25)
    at HTMLButtonElement.addEventListener (zone.js:1907:35)
    at HTMLButtonElement.bindSecondButton ((索引):23:10)
    at ZoneDelegate.invokeTask (zone.js:406:31)
    at Zone.runTask (zone.js:178:47)
    at ____________________Elapsed_2508_ms__At__Mon_Jan_31_2022_20_09_06_GMT_0800_________ (localhost)
    at Object.onScheduleTask (long-stack-trace-zone.js:105:22)
    at ZoneDelegate.scheduleTask (zone.js:386:51)
    at Zone.scheduleTask (zone.js:221:43)
    at Zone.scheduleEventTask (zone.js:247:25)
    at HTMLButtonElement.addEventListener (zone.js:1907:35)
    at main ((索引):20:10)
    at ZoneDelegate.invoke (zone.js:372:26)
    at Zone.run (zone.js:134:43)
Copier après la connexion

通过对比我们知道:不引入zone.js时,我们通过错误调用栈仅仅能够知道,异常是由按钮2的点击函数抛出。而引入了zone.js后,我们不仅知道异常是由按钮2的点击函数抛出,还知道它的点击函数是由按钮1的点击函数绑定的,甚至能够知道最开始的应用启动是main函数触发。这种能够持续追踪多个异步任务的能力在大型复杂项目中异常重要,现在我们来看zone.js是如何做到的吧。

zone.js接管了浏览器提供的异步 API,比如点击事件、计时器等等。也正是因为这样,它才能够对异步操作有更强的控制介入能力,提供更多的能力。现在我们拿点击事件举例,看看它是如何做到的吧。

proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener,..)
Copier après la connexion

上述代码中,proto便指的是EventTarget.prototype,也就是说这行代码重新定义了addEventListener函数。我们继续看看makeAddListener函数做了什么。

function makeAddListener() {
  ......
  // 关键代码1
  nativeListener.apply(this, arguments);
  ......
  // 关键代码2
  const task = zone.scheduleEventTask(source, ...)
  ......
}
Copier après la connexion

该函数主要做了两件事,一是在自定义函数中执行浏览器本身提供的addEventListener函数,另外一个就是为每个点击函数安排了一个事件任务,这也是zone.js对异步 API 有强大介入能力的重要因素。

现在我们再回到本文开头的示例中,看看控制台为什么能够输出完整的完整的函数调用栈。刚刚我们分析过了makeAddListener函数,其中提到它为每个点击函数安排了一个事件任务,也就是zone.scheduleEventTask函数的执行。这个安排事件任务函数最终其实执行的是onScheduleTask:

onScheduleTask: function (..., task) {
  const currentTask = Zone.currentTask;
  let trace = currentTask && currentTask.data && currentTask.data[creationTrace] || [];
  trace = [new LongStackTrace()].concat(trace);
  task.data[creationTrace] = trace;
}
Copier après la connexion

文章开头控制台输出的完整的函数调用栈,存储在currentTask.data[creationTrace]里面,它是一个由LongStackTrace实例组成的数组。每次有异步任务发生时,onScheduleTask函数便把当前函数调用栈存储记录下来,我们看看类LongStackTrace的构造器就知道了:

class LongStackTrace {
    constructor() {
        this.error = getStacktrace();
        this.timestamp = new Date();
    }
}
function getStacktraceWithUncaughtError() {
    return new Error(ERROR_TAG);
}
Copier après la connexion

this.error存储的便是函数调用栈,getStacktrace函数通常调用的是getStacktraceWithUncaughtError函数,我们看到new Error大概就能够知道整个调用栈是如何得来的了。

本文分析的只是zone.js能力的一个示例,如果你希望了解更多功能可以参阅官方文档。通过这个示例,希望读者能对zone.jstutoriel angulaire

"]

Qu'est-ce que Zone ? Le document officiel l'explique ainsi : Zone est un contexte d'exécution qui s'étend sur plusieurs tâches asynchrones. En un mot, Zone possède une capacité particulièrement puissante pour intercepter ou suivre les tâches asynchrones. Ci-dessous, nous utiliserons un exemple pour démontrer ses capacités et analyser brièvement le principe de fonctionnement qui le sous-tend. rrreee

Ceci est une simple page HTML. Lorsque la page se charge, un événement de clic sera ajouté au premier bouton. La fonction de sa fonction d'événement de clic est d'ajouter un événement de clic au deuxième bouton, et la fonction de la fonction d'événement de clic du deuxième bouton est de lancer un événement de clic. exception. Nous cliquons tour à tour sur le premier bouton et le deuxième bouton, et la console affiche ce qui suit : 🎜rrreee🎜Mais si nous commençons à exécuter le code via zone.js, quelle sera la différence dans la sortie de la console ? Ajustons d'abord le code de démarrage : 🎜rrreee🎜La sortie de la console est la suivante : 🎜rrreee🎜Par comparaison, nous savons : lorsque zone.js n'est pas introduit, nous ne pouvons le savoir que via l'appel d'erreur. pile que l'exception est provoquée par le bouton 2 La fonction clic est lancée. Après avoir introduit zone.js, nous savons non seulement que l'exception est levée par la fonction de clic du bouton 2, mais nous savons également que sa fonction de clic est liée par la fonction de clic du bouton 1, et savons même le dernier Le démarrage initial de l'application est déclenché par la fonction main. Cette capacité à suivre en continu plusieurs tâches asynchrones est extrêmement importante dans les projets vastes et complexes. Voyons maintenant comment zone.js le fait. 🎜🎜zone.js reprend l'API asynchrone fournie par le navigateur, comme les événements de clic, les minuteries, etc. C'est précisément grâce à cela qu'il peut disposer de capacités de contrôle et d'intervention plus fortes pour les opérations asynchrones et fournir plus de capacités. Prenons maintenant l'événement click comme exemple et voyons comment cela se déroule. 🎜rrreee🎜Dans le code ci-dessus, proto fait référence à EventTarget.prototype, ce qui signifie que cette ligne de code redéfinit la fonction addEventListener. Continuons à voir ce que fait la fonction makeAddListener. 🎜rrreee🎜Cette fonction fait principalement deux choses. L'une consiste à exécuter la fonction addEventListener fournie par le navigateur lui-même dans la fonction personnalisée. L'autre consiste à organiser une tâche événementielle pour chaque fonction de clic. également un facteur important dans la forte capacité de zone.js à intervenir dans les API asynchrones. 🎜🎜Reprenons maintenant l'exemple du début de cet article et voyons pourquoi la console peut générer une pile d'appels de fonction complète et complète. Nous venons d'analyser la fonction makeAddListener, qui mentionne qu'elle organise une tâche événementielle pour chaque fonction de clic, qui est l'exécution de la fonction zone.scheduleEventTask. Cette fonction de tâche d'événement de planification exécute en fait onScheduleTask :🎜rrreee🎜La pile complète d'appels de fonction sortie par la console au début de l'article, qui est stockée dans currentTask.data[creationTrace] code> , qui est un tableau composé d'instances <code>LongStackTrace. Chaque fois qu'une tâche asynchrone se produit, la fonction onScheduleTask enregistre la pile d'appels de fonction actuelle. Jetons un coup d'œil au constructeur de la classe LongStackTrace : 🎜rrreee🎜this. .error stocke la pile d'appels de fonction. La fonction getStacktrace appelle généralement la fonction getStacktraceWithUncaughtError Nous voyons new Error code>Vous pouvez. je sais probablement comment la totalité de la pile d'appels est obtenue. 🎜🎜Cet article analyse juste un exemple des capacités de zone.js Si vous souhaitez en savoir plus, vous pouvez vous référer à la documentation officielle. Grâce à cet exemple, j'espère que les lecteurs pourront avoir une compréhension générale de zone.js, car c'est également une pierre angulaire indispensable de la détection des changements angulaires. J'expliquerai cet aspect dans le prochain article. 🎜🎜Pour plus de connaissances sur la programmation, veuillez visiter : 🎜Introduction à la programmation🎜 ! ! 🎜

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!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal