> 웹 프론트엔드 > JS 튜토리얼 > Angular의 zone.js에 대한 심층 분석 및 작동 방식

Angular의 zone.js에 대한 심층 분석 및 작동 방식

青灯夜游
풀어 주다: 2022-02-15 10:11:36
앞으로
2452명이 탐색했습니다.

이 기사에서는 Angular의 zone.js를 살펴보고, 예제를 통해 zone.js의 기능을 보여주고, 그 뒤에 있는 작동 원리를 간략하게 분석합니다. 모든 사람에게 도움이 되기를 바랍니다.

Angular의 zone.js에 대한 심층 분석 및 작동 방식

아마도 Angular가 zone.js를 사용한다는 말을 들어보셨을 것입니다. 그런데 Angular는 왜 zone.js를 사용하고 어떤 기능을 제공할 수 있나요? 오늘 우리는 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.jsangular tutorial

"]

Zone이 무엇인가요? 공식 문서에서는 다음과 같이 설명합니다. Zone은 여러 비동기 작업을 포괄하는 실행 컨텍스트입니다. 간단히 말해서 Zone은 비동기 작업을 가로채거나 추적하는 특히 강력한 기능을 가지고 있습니다. 아래에서는 예를 사용하여 그 기능을 보여주고 그 뒤에 있는 작동 원리를 간략하게 분석합니다. rrreee

이것은 간단한 HTML 페이지입니다. 페이지가 로드되면 첫 번째 버튼에 클릭 이벤트가 추가됩니다. 클릭 이벤트 기능의 기능은 두 번째 버튼에 클릭 이벤트를 추가하는 것이고, 두 번째 버튼의 클릭 이벤트 기능은 이벤트를 발생시키는 것입니다. 예외. 첫 번째 버튼과 두 번째 버튼을 차례로 클릭하면 콘솔에 다음과 같이 표시됩니다. 🎜rrreee🎜그러나 zone.js를 통해 코드를 실행하기 시작하면 콘솔 출력의 차이점은 무엇입니까? ? 먼저 시작 코드를 조정해 보겠습니다. 🎜rrreee🎜콘솔 출력은 다음과 같습니다. 🎜rrreee🎜비교를 통해 알 수 있습니다. zone.js가 도입되지 않은 경우 오류 호출을 통해서만 알 수 있습니다. 버튼 2로 인해 예외가 발생한 스택 클릭 기능이 발생합니다. zone.js를 소개한 후, 우리는 버튼 2의 클릭 기능에 의해 예외가 발생한다는 것을 알 뿐만 아니라 해당 클릭 기능이 버튼 1의 클릭 기능에 묶여 있다는 것도 알게 되었습니다. 최신 초기 애플리케이션 시작은 main 함수에 의해 트리거됩니다. 여러 비동기 작업을 지속적으로 추적하는 기능은 크고 복잡한 프로젝트에서 매우 중요합니다. 이제 zone.js가 이를 어떻게 수행하는지 살펴보겠습니다. 🎜🎜zone.js는 클릭 이벤트, 타이머 등과 같이 브라우저에서 제공하는 비동기 API를 대신합니다. 비동기 작업에 대한 더 강력한 제어 및 개입 기능을 보유하고 더 많은 기능을 제공할 수 있는 것은 바로 이 때문입니다. 이제 클릭 이벤트를 예로 들어 이것이 어떻게 수행되는지 살펴보겠습니다. 🎜rrreee🎜위 코드에서 protoEventTarget.prototype을 참조합니다. 이는 이 코드 줄이 addEventListener 함수를 재정의한다는 의미입니다. makeAddListener 함수가 수행하는 작업을 계속 살펴보겠습니다. 🎜rrreee🎜이 함수는 주로 두 가지 작업을 수행합니다. 하나는 브라우저 자체에서 제공하는 addEventListener 함수를 사용자 정의 함수에서 실행하는 것입니다. 또한 비동기 API에 개입하는 zone.js의 강력한 기능에 있어서 중요한 요소이기도 합니다. 🎜🎜이제 이 글의 시작 부분에 있는 예로 돌아가 콘솔이 완전하고 완전한 함수 호출 스택을 출력할 수 있는 이유를 살펴보겠습니다. 우리는 방금 zone.scheduleEventTask 함수의 실행인 각 클릭 함수에 대해 이벤트 작업을 정렬한다고 언급한 makeAddListener 함수를 분석했습니다. 이 일정 이벤트 작업 함수는 실제로 onScheduleTask를 실행합니다.🎜rrreee🎜기사 시작 부분에 있는 콘솔에서 출력된 전체 함수 호출 스택은 currentTask.data[creationTrace]에 저장되어 있습니다. code> - <code>LongStackTrace 인스턴스로 구성된 배열입니다. 비동기 작업이 발생할 때마다 onScheduleTask 함수는 현재 함수 호출 스택 저장소를 기록합니다. LongStackTrace 클래스의 생성자를 살펴보겠습니다. 🎜rrreee🎜 this.error는 함수 호출 스택을 저장합니다. getStacktrace 함수는 일반적으로 getStacktraceWithUncaughtError 함수를 호출합니다. 아마도 전체 호출 스택을 얻는 방법을 알 수 있을 것입니다. 🎜🎜이 글은 zone.js 기능의 예를 분석한 것입니다. 더 많은 기능을 알고 싶다면 공식 문서를 참조하세요. 이 예제를 통해 독자들이 zone.js에 대한 전반적인 이해를 가질 수 있기를 바랍니다. 이는 Angular 변경 감지에 없어서는 안 될 초석이기도 하기 때문입니다. 이 부분에 대해서는 다음 글에서 설명하겠습니다. 🎜🎜더 많은 프로그래밍 관련 지식을 보려면 🎜프로그래밍 소개🎜를 방문하세요! ! 🎜

위 내용은 Angular의 zone.js에 대한 심층 분석 및 작동 방식의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿