Angular中的zone.js工作原理是如何深入浅析改写的?

2026-04-03 07:381阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1922个文字,预计阅读时间需要8分钟。

Angular中的zone.js工作原理是如何深入浅析改写的?

本文将带大家了解Angular中的zone.js,并通过一个示例展示其功能。zone.js是Angular的核心库之一,它提供了强大的异步处理能力。下面,我们将简要分析zone.js背后的工作原理,希望对大家有所帮助!

或许您听说过Angular使用了zone.js,但您可能想知道:Angular为什么使用zone.js?以下是原因:

1. 处理异步事件:zone.js允许Angular框架处理异步事件,如定时器、事件监听等,而不会阻塞主线程。

2.检测内存泄漏:zone.js可以帮助开发者检测内存泄漏,确保应用性能稳定。

3.简化测试:zone.js简化了异步测试的编写,使单元测试和集成测试更加容易。

以下是一个使用zone.js的示例:

javascript

import { Component } from '@angular/core';import { Zone } from 'zone.js';

@Component({ selector: 'app-root', template: `{{ counter }}`})export class AppComponent { counter=0;

constructor() { // 创建一个新的zone const zone=Zone.current.fork({ onMicrotaskEmpty: ()=> { this.counter++; } });

// 在zone中运行代码 zone.run(()=> { setTimeout(()=> { console.log('Timer triggered'); }, 1000); }); }}

在这个示例中,我们创建了一个新的zone,并在其中设置了microtask空执行的回调函数。每当microtask队列为空时,都会触发回调,从而更新`counter`的值。

总结,zone.js是Angular框架中不可或缺的一部分,它为异步编程提供了强大的支持。希望本文能帮助大家更好地理解zone.js的工作原理和用途。如果您对Angular或zone.js有任何疑问,欢迎继续探讨!

本篇文章带大家了解一下Angular 中的 zone.js,通过一个示例来展示zone.js的能力,并简单剖析一下背后的工作原理,希望对大家有所帮助!

Angular中的zone.js工作原理是如何深入浅析改写的?

或许你听说过 Angular 使用了zone.js, 但 Angular 为什么要使用zone.js, 它能够提供哪些功能呢?今天我们单独写一篇文章聊聊zone.js,关于它在 Angular 框架中发挥的作用将在下一篇文章讲述。

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

<button id="b1">Bind Error</button> <button id="b2">Cause Error</button> <script> function main() { b1.addEventListener('click', bindSecondButton); } function bindSecondButton() { b2.addEventListener('click', throwError); } function throwError() { throw new Error('aw shucks'); } main(); </script>

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

(索引):26 Uncaught Error: aw shucks at HTMLButtonElement.throwError ((索引):26:13)

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

Zone.current.fork( { name: 'error', onHandleError: function (parentZoneDelegate, currentZone, targetZone, error) { console.log(error.stack); } } ).fork(Zone.longStackTraceZoneSpec).run(main);

此时控制台输出如下:

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)

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

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

proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener,..)

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

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

该函数主要做了两件事,一是在自定义函数中执行浏览器本身提供的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; }

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

class LongStackTrace { constructor() { this.error = getStacktrace(); this.timestamp = new Date(); } } function getStacktraceWithUncaughtError() { return new Error(ERROR_TAG); }

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

本文分析的只是zone.js能力的一个示例,如果你希望了解更多功能可以参阅官方文档。通过这个示例,希望读者能对zone.js有一个大概的认识,因为它也是 Angular 变更检测不可或缺的基石。这方面的内容我将在下一篇文章中讲解。

更多编程相关知识,请访问:编程入门!!

以上就是深入浅析Angular 中的 zone.js,聊聊工作原理的详细内容,更多请关注自由互联其它相关文章!

本文共计1922个文字,预计阅读时间需要8分钟。

Angular中的zone.js工作原理是如何深入浅析改写的?

本文将带大家了解Angular中的zone.js,并通过一个示例展示其功能。zone.js是Angular的核心库之一,它提供了强大的异步处理能力。下面,我们将简要分析zone.js背后的工作原理,希望对大家有所帮助!

或许您听说过Angular使用了zone.js,但您可能想知道:Angular为什么使用zone.js?以下是原因:

1. 处理异步事件:zone.js允许Angular框架处理异步事件,如定时器、事件监听等,而不会阻塞主线程。

2.检测内存泄漏:zone.js可以帮助开发者检测内存泄漏,确保应用性能稳定。

3.简化测试:zone.js简化了异步测试的编写,使单元测试和集成测试更加容易。

以下是一个使用zone.js的示例:

javascript

import { Component } from '@angular/core';import { Zone } from 'zone.js';

@Component({ selector: 'app-root', template: `{{ counter }}`})export class AppComponent { counter=0;

constructor() { // 创建一个新的zone const zone=Zone.current.fork({ onMicrotaskEmpty: ()=> { this.counter++; } });

// 在zone中运行代码 zone.run(()=> { setTimeout(()=> { console.log('Timer triggered'); }, 1000); }); }}

在这个示例中,我们创建了一个新的zone,并在其中设置了microtask空执行的回调函数。每当microtask队列为空时,都会触发回调,从而更新`counter`的值。

总结,zone.js是Angular框架中不可或缺的一部分,它为异步编程提供了强大的支持。希望本文能帮助大家更好地理解zone.js的工作原理和用途。如果您对Angular或zone.js有任何疑问,欢迎继续探讨!

本篇文章带大家了解一下Angular 中的 zone.js,通过一个示例来展示zone.js的能力,并简单剖析一下背后的工作原理,希望对大家有所帮助!

Angular中的zone.js工作原理是如何深入浅析改写的?

或许你听说过 Angular 使用了zone.js, 但 Angular 为什么要使用zone.js, 它能够提供哪些功能呢?今天我们单独写一篇文章聊聊zone.js,关于它在 Angular 框架中发挥的作用将在下一篇文章讲述。

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

<button id="b1">Bind Error</button> <button id="b2">Cause Error</button> <script> function main() { b1.addEventListener('click', bindSecondButton); } function bindSecondButton() { b2.addEventListener('click', throwError); } function throwError() { throw new Error('aw shucks'); } main(); </script>

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

(索引):26 Uncaught Error: aw shucks at HTMLButtonElement.throwError ((索引):26:13)

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

Zone.current.fork( { name: 'error', onHandleError: function (parentZoneDelegate, currentZone, targetZone, error) { console.log(error.stack); } } ).fork(Zone.longStackTraceZoneSpec).run(main);

此时控制台输出如下:

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)

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

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

proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener,..)

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

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

该函数主要做了两件事,一是在自定义函数中执行浏览器本身提供的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; }

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

class LongStackTrace { constructor() { this.error = getStacktrace(); this.timestamp = new Date(); } } function getStacktraceWithUncaughtError() { return new Error(ERROR_TAG); }

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

本文分析的只是zone.js能力的一个示例,如果你希望了解更多功能可以参阅官方文档。通过这个示例,希望读者能对zone.js有一个大概的认识,因为它也是 Angular 变更检测不可或缺的基石。这方面的内容我将在下一篇文章中讲解。

更多编程相关知识,请访问:编程入门!!

以上就是深入浅析Angular 中的 zone.js,聊聊工作原理的详细内容,更多请关注自由互联其它相关文章!