Angular 学习笔记 (七) - Observables

Observable 提供了在应用程序各部分之间传递消息的支持。它们经常在Angular中使用,是一种用于事件处理、异步编程和处理多个值的技术。

观察者模式是一种软件设计模式,在这种模式中,一个对象(称为subject)维护一个称为观察者的依赖项列表,并自动通知它们状态的更改。此模式与发布/订阅设计模式相似(但不完全相同)。

Observable 是声明性的——也就是说,您定义了一个用于发布值的函数,但是在消费者订阅该函数之前不会执行该函数。订阅的消费者然后接收通知,直到函数完成,或者直到它们退订。

一个可观察对象可以交付任意类型的多个值——文字、消息或事件,这取决于上下文。接收值的API无论同步还是异步传递值都是相同的。因为设置和拆卸逻辑都是由observable处理的,所以你的应用代码只需要担心订阅和取消订阅的问题。无论流是击键、HTTP响应还是间隔计时器,监听值和停止监听的接口都是相同的。

由于这些优点,observable在Angular中被广泛使用,在应用开发中也同样如此。

 

Angular继承rxjs模块:

 

 

 

rxjs官方文档:

https://www.learnrxjs.io/

 

一. Observable

一般来说,很少自定义Observable,用其提供的Observer就可以实现功能。

一个简单的用Interval实现网页标题不断刷新时间的例子:

 1 import { Component, OnInit } from '@angular/core';
 2 import { Title } from '@angular/platform-browser';
 3 import { interval } from 'rxjs';
 4 
 5 @Component({
 6   selector: 'app-root',
 7   templateUrl: './app.component.html',
 8   styleUrls: ['./app.component.css']
 9 })
10 export class AppComponent implements OnInit{
11 
12   constructor(private titleService: Title) {}
13 
14   ngOnInit() {
15     interval(1000).subscribe(val => {
16       const timestamp = new Date().toLocaleString();
17       this.titleService.setTitle(`Hello ${timestamp}`);
18     });
19   }
20 }

 

自定义Observable的例子,包含error handling和complete

  • 这里一旦触发了error,observer会停止,不会触发complete
  • Observable订阅了记得unsubscribe(),否则会内存泄漏
 1 import { Component, OnInit, OnDestroy } from '@angular/core';
 2 import { interval, Observable, observable, Subscription} from 'rxjs';
 3 import { map, filter } from 'rxjs/operators';
 4 
 5 @Component({
 6   selector: 'app-home',
 7   templateUrl: './home.component.html',
 8   styleUrls: ['./home.component.css']
 9 })
10 export class HomeComponent implements OnInit, OnDestroy {
11 
12   private firstObsSubscription: Subscription;
13 
14   constructor() { }
15 
16   ngOnInit() {
17     const customIntervalObservable = new Observable(observer => {
18       let count = 0;
19       setInterval(() => {
20         observer.next(count);
21         if (count == 2){
22           observer.complete();
23         }
24         if (count > 3) {
25           observer.error(new Error('Count is bigger than 3'));
26         }
27         count++;
28       }, 1000);
29     });
30 
31     this.firstObsSubscription = customIntervalObservable.pipe(filter((data:number) => {
32       return (data % 2) == 0;
33     }), map((data:number) => {
34       return 'Round: ' + (data + 1);
35     })).subscribe(data => {
36       console.log(data);
37     }, error => {
38       console.log(error);
39       alert(error.message);
40     }, () => {
41       console.log('Completed');
42     });
43   }
44 
45   ngOnDestroy() {
46     this.firstObsSubscription.unsubscribe();
47   }
48   
49 }
50  

 

二. Operator

rxjs提供了很多Operator用于流处理的操作,上例中已经使用了map,filter

参考文档:https://www.learnrxjs.io/learn-rxjs/operators

 

三. Subject

Subject是一种特殊类型的Observable,它在多个观察者之间共享一条执行路径。

你可以把它想象成一个演讲者在满屋子的人面前对着麦克风说话。他们的信息(主题)正在被同时传送给许多人(多播)(观察者)。这是多播的基础。典型的观察可以与1对1的对话相媲美。

  • Subject - No initial value or replay behavior.

  • AsyncSubject - Emits latest value to observers upon completion.

  • BehaviorSubject - Requires an initial value and emits its current value (last emitted item) to new subscribers.

  • ReplaySubject - Emits specified number of last emitted values (a replay) to new subscribers.

示例,Subject在service中使用,替代EventEmitter

定义Service:

1 import { Injectable, EventEmitter } from "@angular/core";
2 import { Subject } from 'rxjs';
3 
4 @Injectable({providedIn: 'root'})
5 export class UserService {
6     activatedEmitter = new Subject<boolean>();
7 }

触发Subject:

onActivate() {
    this.userService.activatedEmitter.next(true);
}

subscribe,unsubscribe :

 1 import { Component, OnInit, OnDestroy } from '@angular/core';
 2 import { Subscription } from 'rxjs';
 3 import { UserService } from './user.service';
 4 
 5 @Component({
 6   selector: 'app-root',
 7   templateUrl: './app.component.html',
 8   styleUrls: ['./app.component.css']
 9 })
10 export class AppComponent implements OnInit, OnDestroy {
11 
12   userActivated = false;
13   private activatedSub: Subscription;
14 
15   constructor(private userService: UserService) {}
16 
17   ngOnInit() {
18     this.activatedSub = this.userService.activatedEmitter.subscribe(
19       didActive => {
20         this.userActivated = didActive;
21       }
22     );
23   }
24 
25   ngOnDestroy() {
26     this.activatedSub.unsubscribe();
27   }
28 }

 

 

 

 

posted @ 2021-04-12 17:24  Asp1rant  阅读(403)  评论(0编辑  收藏  举报