首頁 web前端 js教程 深入淺析Angular 中的 zone.js,聊聊工作原理

深入淺析Angular 中的 zone.js,聊聊工作原理

Feb 07, 2022 am 10:09 AM
angular

這篇文章帶大家了解一下Angular 中的 zone.js,透過一個例子來展示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(&#39;click&#39;, bindSecondButton);
  }
  function bindSecondButton() {
    b2.addEventListener(&#39;click&#39;, throwError);
  }
  function throwError() {
    throw new Error(&#39;aw shucks&#39;);
  }
  main();
</script>
登入後複製

這是一個簡單的 HTML 頁面。頁面載入時會為第一個按鈕新增點擊事件,其點擊事件函數的功能是為第二個按鈕新增點擊事件,而第二個按鈕的點擊事件函數功能則是拋出一個例外。我們依序點擊第一個按鈕和第二個按鈕,控制台顯示如下:

(索引):26 Uncaught Error: aw shucks
    at HTMLButtonElement.throwError ((索引):26:13)
登入後複製

但是如果我們透過zone.js啟動運行程式碼,控制台輸出會有什麼不同呢,我們先調整啟動程式碼:

  Zone.current.fork(
      {
        name: &#39;error&#39;,
        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,聊聊工作原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

聊聊Angular中的元資料(Metadata)和裝飾器(Decorator) 聊聊Angular中的元資料(Metadata)和裝飾器(Decorator) Feb 28, 2022 am 11:10 AM

這篇文章繼續Angular的學習,帶大家了解Angular中的元數據和裝飾器,簡單了解一下他們的用法,希望對大家有幫助!

如何在Ubuntu 24.04上安裝Angular 如何在Ubuntu 24.04上安裝Angular Mar 23, 2024 pm 12:20 PM

Angular.js是一種可自由存取的JavaScript平台,用於建立動態應用程式。它允許您透過擴展HTML的語法作為模板語言,以快速、清晰地表示應用程式的各個方面。 Angular.js提供了一系列工具,可協助您編寫、更新和測試程式碼。此外,它還提供了許多功能,如路由和表單管理。本指南將討論在Ubuntu24上安裝Angular的方法。首先,您需要安裝Node.js。 Node.js是一個基於ChromeV8引擎的JavaScript運行環境,可讓您在伺服器端執行JavaScript程式碼。要在Ub

angular學習之詳解狀態管理器NgRx angular學習之詳解狀態管理器NgRx May 25, 2022 am 11:01 AM

這篇文章帶大家深入了解angular的狀態管理器NgRx,介紹一下NgRx的使用方法,希望對大家有幫助!

一文探究Angular中的服務端渲染(SSR) 一文探究Angular中的服務端渲染(SSR) Dec 27, 2022 pm 07:24 PM

你知道 Angular Universal 嗎?可以幫助網站提供更好的 SEO 支援哦!

如何使用PHP和Angular進行前端開發 如何使用PHP和Angular進行前端開發 May 11, 2023 pm 04:04 PM

隨著網路的快速發展,前端開發技術也不斷改進與迭代。 PHP和Angular是兩種廣泛應用於前端開發的技術。 PHP是一種伺服器端腳本語言,可以處理表單、產生動態頁面和管理存取權限等任務。而Angular是一種JavaScript的框架,可以用來開發單一頁面應用程式和建構元件化的網頁應用程式。本篇文章將介紹如何使用PHP和Angular進行前端開發,以及如何將它們

Angular + NG-ZORRO快速開發一個後台系統 Angular + NG-ZORRO快速開發一個後台系統 Apr 21, 2022 am 10:45 AM

這篇文章跟大家分享一個Angular實戰,了解一下angualr 結合 ng-zorro 如何快速開發一個後台系統,希望對大家有幫助!

淺析angular中怎麼使用monaco-editor 淺析angular中怎麼使用monaco-editor Oct 17, 2022 pm 08:04 PM

angular中怎麼使用monaco-editor?以下這篇文章記錄下最近的一次業務中用到的 m​​onaco-editor 在 angular 中的使用,希望對大家有幫助!

淺析Angular中的獨立組件,看看怎麼使用 淺析Angular中的獨立組件,看看怎麼使用 Jun 23, 2022 pm 03:49 PM

這篇文章帶大家了解Angular中的獨立元件,看看怎麼在Angular中建立一個獨立元件,怎麼在獨立元件中導入已有的模組,希望對大家有幫助!

See all articles