Angular中的zone.js有什么作用,原理是怎样的
Admin 2022-07-15 群英技术资讯 851 次浏览
今天这篇给大家分享的知识是“Angular中的zone.js有什么作用,原理是怎样的”,小编觉得挺不错的,对大家学习或是工作可能会有所帮助,对此分享发大家做个参考,希望这篇“Angular中的zone.js有什么作用,原理是怎样的”文章能帮助大家解决问题。
或许你听说过 Angular 使用了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('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 变更检测不可或缺的基石。这方面的内容我将在下一篇文章中讲解。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
如何理解JS作用域的作用是什么呢??今天来给大家说说看js中静态作用域有什么用处的相关内容,小编觉得这篇文章不错,所以分享给大家。
这篇文章给大家分享的是隐藏域的作用和获取隐藏域中的值的方法,文中的获取隐藏域中的值的示例是使用jQuery实现的,下文有详细的介绍,有需要的朋友可以参考,接下来就跟随小编来一起学习一下吧!
这篇文章我们来了解JavaScript中的style,JavaScript中,我们经常需要使用style,style的意思是“样式”、“设置样式”,style属性是一个全局属性,因此对于style的使用是一定需要掌握的,对此这篇就给大家来简单的介绍一下style及其基本使用,有需要的朋友可以参考,接下来就跟随小编来一起学习一下吧!
这篇文章主要为大家介绍了Vue3 中有场景是 reactive 能做而 ref 做不了的使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
在前端开发时,点击父菜单弹出子菜单功能是比较经常遇到需求,这篇文章就主要介绍用JavaScript实现点击出现子菜单,以下是简易的实现效果以及具体代码展示,感兴趣的朋友就继续往下看吧。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008