新聞中心
這篇文章主要介紹“Angular中zone.js的工作原理是什么”的相關(guān)知識(shí),小編通過實(shí)際案例向大家展示操作過程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“Angular中zone.js的工作原理是什么”文章能幫助大家解決問題。
成都創(chuàng)新互聯(lián)專注于沁陽網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供沁陽營(yíng)銷型網(wǎng)站建設(shè),沁陽網(wǎng)站制作、沁陽網(wǎng)頁(yè)設(shè)計(jì)、沁陽網(wǎng)站官網(wǎng)定制、成都小程序開發(fā)服務(wù),打造沁陽網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供沁陽網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
什么是 Zone ? 官方文檔是這么解釋的:Zone 是一個(gè)跨多個(gè)異步任務(wù)的執(zhí)行上下文。一句話總結(jié)來說,Zone 在攔截或追蹤異步任務(wù)方面有著特別強(qiáng)大的能力。下面我們將通過一個(gè)示例來展示它的能力,并簡(jiǎn)單剖析一下背后的工作原理。
這是一個(gè)簡(jiǎn)單的 HTML 頁(yè)面。頁(yè)面加載時(shí)會(huì)給第一個(gè)按鈕添加點(diǎn)擊事件,其點(diǎn)擊事件函數(shù)的功能是給第二個(gè)按鈕添加點(diǎn)擊事件,而第二個(gè)按鈕的點(diǎn)擊事件函數(shù)功能是拋出一個(gè)異常。我們依次點(diǎn)擊第一個(gè)按鈕和第二個(gè)按鈕,控制臺(tái)顯示如下:
(索引):26 Uncaught Error: aw shucks at HTMLButtonElement.throwError ((索引):26:13)
但是如果我們通過zone.js
啟動(dòng)運(yùn)行代碼,控制臺(tái)輸出會(huì)有什么不同呢,我們先調(diào)整啟動(dòng)代碼:
Zone.current.fork( { name: 'error', onHandleError: function (parentZoneDelegate, currentZone, targetZone, error) { console.log(error.stack); } } ).fork(Zone.longStackTraceZoneSpec).run(main);
此時(shí)控制臺(tái)輸出如下:
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)
通過對(duì)比我們知道:不引入zone.js
時(shí),我們通過錯(cuò)誤調(diào)用棧僅僅能夠知道,異常是由按鈕2的點(diǎn)擊函數(shù)拋出。而引入了zone.js
后,我們不僅知道異常是由按鈕2的點(diǎn)擊函數(shù)拋出,還知道它的點(diǎn)擊函數(shù)是由按鈕1的點(diǎn)擊函數(shù)綁定的,甚至能夠知道最開始的應(yīng)用啟動(dòng)是main
函數(shù)觸發(fā)。這種能夠持續(xù)追蹤多個(gè)異步任務(wù)的能力在大型復(fù)雜項(xiàng)目中異常重要,現(xiàn)在我們來看zone.js
是如何做到的吧。
zone.js
接管了瀏覽器提供的異步 API,比如點(diǎn)擊事件、計(jì)時(shí)器等等。也正是因?yàn)檫@樣,它才能夠?qū)Ξ惒讲僮饔懈鼜?qiáng)的控制介入能力,提供更多的能力?,F(xiàn)在我們拿點(diǎn)擊事件舉例,看看它是如何做到的吧。
proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener,..)
上述代碼中,proto
便指的是EventTarget.prototype
,也就是說這行代碼重新定義了addEventListener
函數(shù)。我們繼續(xù)看看makeAddListener
函數(shù)做了什么。
function makeAddListener() { ...... // 關(guān)鍵代碼1 nativeListener.apply(this, arguments); ...... // 關(guān)鍵代碼2 const task = zone.scheduleEventTask(source, ...) ...... }
該函數(shù)主要做了兩件事,一是在自定義函數(shù)中執(zhí)行瀏覽器本身提供的addEventListener
函數(shù),另外一個(gè)就是為每個(gè)點(diǎn)擊函數(shù)安排了一個(gè)事件任務(wù),這也是zone.js
對(duì)異步 API 有強(qiáng)大介入能力的重要因素。
現(xiàn)在我們?cè)倩氐奖疚拈_頭的示例中,看看控制臺(tái)為什么能夠輸出完整的完整的函數(shù)調(diào)用棧。剛剛我們分析過了makeAddListener
函數(shù),其中提到它為每個(gè)點(diǎn)擊函數(shù)安排了一個(gè)事件任務(wù),也就是zone.scheduleEventTask
函數(shù)的執(zhí)行。這個(gè)安排事件任務(wù)函數(shù)最終其實(shí)執(zhí)行的是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; }
文章開頭控制臺(tái)輸出的完整的函數(shù)調(diào)用棧,存儲(chǔ)在currentTask.data[creationTrace]
里面,它是一個(gè)由LongStackTrace
實(shí)例組成的數(shù)組。每次有異步任務(wù)發(fā)生時(shí),onScheduleTask
函數(shù)便把當(dāng)前函數(shù)調(diào)用棧存儲(chǔ)記錄下來,我們看看類LongStackTrace
的構(gòu)造器就知道了:
class LongStackTrace { constructor() { this.error = getStacktrace(); this.timestamp = new Date(); } } function getStacktraceWithUncaughtError() { return new Error(ERROR_TAG); }
this.error
存儲(chǔ)的便是函數(shù)調(diào)用棧,getStacktrace
函數(shù)通常調(diào)用的是getStacktraceWithUncaughtError
函數(shù),我們看到new Error
大概就能夠知道整個(gè)調(diào)用棧是如何得來的了。
關(guān)于“Angular中zone.js的工作原理是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
網(wǎng)頁(yè)題目:Angular中zone.js的工作原理是什么
網(wǎng)頁(yè)鏈接:http://fisionsoft.com.cn/article/jgodhe.html