关于ZONE.js / 复习一下RXJS的subject

58 篇文章 3 订阅
13 篇文章 0 订阅

今天看项目看到这么一段

this._zone.run(() => { });

什么是 Zone? Zone 是一种用于拦截和跟踪异步工作的机制。


什么是 NgZone? Zone.js 将会对每一个异步操作创建一个 task。一个 task 运行于一个 Zone 中。通常来说, 在 Angular 应用中,每个 task 都会在 “Angular” Zone 中运行,这个 Zone 被称为 NgZone。一个 Angular 应用中只存在一个 Angular Zone,而变更检测只会由 运行于这个 NgZone 中的异步操作触发。


如何在代码中上手 NgZone? 先了解 run 与 runOutsideAngular 两个 API 即可。

以上涉及到两个 API,再加上一些常见用法。我们来看看在不同场景下,代码都该怎么写。

首先,函数 runOutsideAngular 用于确保代码于 NgZone 之外运行,即保证 Angular 的变更检测不会因为相关代码而触发。

在某些场景中因为自动变更检测触发过于频繁而导致性能下降时,你可能会希望可以自己掌握全局。

如果你仍然希望利用Zone.js的优势,但又想要控制能够触发变更检测的场景/动作,你可以采用如下方法。

通过注入 NgZone, 你可以使用一个 API 决定”一个异步操作是否需要在 NgZone 中执行“。函数 runOutsideAngular 用于确保代码于 NgZone 之外运行,保证变更检测不会因为相关代码而触发。

这儿有一个例子:

constructor(private ngZone: NgZone) {
  this.ngZone.runOutsideAngular(() => {
    // this will not trigger change detection
    setInterval(() => doSomething(), 100)
  });
}
constructor(private ngZone: NgZone) {
  this.ngZone.runOutsideAngular(() => {
    // 以下代码不会触发变更检测
    setInterval(() => doSomething(), 100)
  });
}


run 方法的目的与 runOutsideAngular 正好相反:任何写在 run 里的方法,都会进入 Angular Zone 的管辖范围。(组里大佬拿来强制更新Angular的视图,学到了)

// 此处的 num 会实时更新
import { Component, NgZone } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <p>
      <label>Count: </label>
    
  </p>  
  `
})
export class AppComponent {
  num = 0;
  constructor(private zone: NgZone) {
    this.zone.runOutsideAngular(() => {
      let i = 0;
      const token = setInterval(() => {
        this.zone.run(() => {
          this.num = ++i;
        })
        console.log(this.num);
        if (i == 10) {
          clearInterval(token);
        }
      }, 1000);
    })
  }
}

RxJS 与 Zone.js 如何一起使用

angular/NON-STANDARD-APIS.md at main · angular/angular · GitHubThe modern web developer’s platform. Contribute to angular/angular development by creating an account on GitHub.https://github.com/angular/angular/blob/main/packages/zone.js/NON-STANDARD-APIS.md#usage

默认情况下,RxJS 与 Zone.js 可能不会如你预期的那般运行。比如,你可能会把 Observable 相关代码封装进一个函数,并将其传递到 NgZone.runOutsideAngular 方法中,却仍然以在NgZone 内部运行的任务结束这个 Observable(与 Zone 外创建数据流,于 Zone 内订阅数据流)。

使用 RxJS 时,应始终从Zone.js导入相关补丁,以确保 RxJS 以”合理“的方式工作。在 subscription,operator 或 Observable 构造时,它会记住当前所处的 Zone,并且始终在该 Zone 中运行,这与你订阅的 Zone 无关,两者完全独立。

你可以依照如下的方案给 Zone.js 和 RxJS 的适配打补丁,通常在 polyfill.ts 文件中。

import ‘zone.js/dist/zone-patch-rxjs’;

另外:Angular In Depth - 知乎

 插个链接,需要重点看一下这系列的文章。

=================================split=====================================

Subject? 

每个 Subject 都是 Observable 

每个 Subject 都是Observer

我们为 Subject 添加了两个观察者,然后给 Subject 提供一些值:

var subject = new Rx.Subject();

subject.subscribe({
  next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
  next: (v) => console.log('observerB: ' + v)
});

subject.next(1);
subject.next(2);

下面是控制台的输出:

observerA: 1
observerB: 1
observerA: 2
observerB: 2

因为 Subject 是观察者,这也就在意味着你可以把 Subject 作为参数传给任何 Observable 的 subscribe 方法,如下面的示例所展示的:

var subject = new Rx.Subject();

subject.subscribe({
  next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
  next: (v) => console.log('observerB: ' + v)
});

var observable = Rx.Observable.from([1, 2, 3]);

observable.subscribe(subject); // 你可以提供一个 Subject 进行订阅

执行结果:

observerA: 1
observerB: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3

使用上面的方法,我们基本上只是通过 Subject 将单播的 Observable 执行转换为多播的。这也说明了 Subjects 是将任意 Observable 执行共享给多个观察者的唯一方式。

还有一些特殊类型的 SubjectBehaviorSubjectReplaySubject 和 AsyncSubject

 这三个变体功能及其强大!一定要学会!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董厂长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值