NG | 观察者模式

748 阅读4分钟

一、观察者模式

用处:在需要进行事件处理、异步编程和处理多个值的时候,可观察对象相对其它技术有着显著的优点。

简单的流程:

一个观察者(Observer)通过subscribe()方法订阅一个可观察对象(Observable)。

订阅之后观察者(Obsever)对可观察者(Observable)发射的数据或数据序列就能作出响应(next函数发射数据)。

涉及到三个东西:观察者(Observer)、可观察者(Observable)、订阅(subscribe)。

import { of, Observable, Observer, Subject } from "rxjs";
import { filter, map } from 'rxjs/operators';
function f1() {
    // 创建一个可观察者对象-Observable,发射三个数据1、2、3
    let observable = of(1, 2, 3);
    // 创建一个观察者对象-Observer(处理next、error、complete回调)
        const myObserver = {
            next: x => console.log('Observer got a next value: ' + x),
            error: err => console.error('Observer got an error: ' + err),
            complete: () => console.log('Observer got a complete notification'),
        };
        // 通过Observable的subscribe函数,观察者去订阅并处理可观察者的消息
        myObservable.subscribe(myObserver);
}
f1();

作为发布者,你创建一个 Observable 的实例,其中定义了一个*订阅者(subscriber)*函数。 当有消费者调用 subscribe() 方法时,这个函数就会执行。 订阅者函数用于定义“如何获取或生成那些要发布的值或消息”。

在Angular中,所有的HTTP请求返回的都是Observable;
Observable可以发送任意多值,并且,在被订阅之前,它是不会执行的!
observable:可观察对象,用来发布数据的
observer:观察者,用来消费数据的(订阅之后才能消费)

订阅时要先调用可观察对象的实例的 subscribe() 方法,并把一个观察者对象传给它,用来接收通知。
observable.subscribe(observer)
1、Observer(观察者)

Observer(观察者)是用于接收Observable(可观察者)对象通知的**处理器(**说白了就是就是接收Observable发送过来的消息)。

Observer(观察者)需要实现Observer接口,也就是next\error\complete

 const myObserver = {
     // next方法接受一个参数,而这个参数就是生产者发送过来的值
     next: x => console.log('Observer got a next value: ' + x),
     error: err => console.error('Observer got an error: ' + err),
     complete: () => console.log('Observer got a complete notification'),
 };
2、Observable(可观察者)

使用Observable构造函数可以创建任何类型的可观察流。

当执行可观察对象的subscribe()方法时,这个构造函数就会把它接收到的参数作为订阅函数来运行。

订阅函数需要接收一个Observer对象,并把值发布给观察者对象的next()方法。

observable通过next发布值

observer通过next接收值

function f5() {
    function sequenceSubscriber(observer) {
        observer.next(1);
        observer.next(2);
        observer.next(3);
        observer.complete();
        return { unsubscribe() { } };
    }
   
    //执行subscrirbe时,构造函数就会把它接收到的参数(也就是执行上面那个函数,也就是发布值)作为订阅函数来运行。
    //这也就是为什么说,Observable可以发送任意多值,并且,在被订阅之前,它是不会执行的!
    const sequence = new Observable(sequenceSubscriber);
    sequence.subscribe({
        // next方法接受一个参数,而这个参数就是生产者发送过来的值
        next(num) { console.log(num); },
        complete() { console.log('Finished sequence'); }
    });
}

f5();
//构造函数源码 
//其实就是将参数设置为可观察者的订阅函数
constructor(subscribe) {
    this._isScalar = false;
    if (subscribe) {
   		this._subscribe = subscribe;
    }
}
3、Subscribing(订阅)

只有当有人订阅Observable的实例时,它才会开始发布值。

订阅就是去调用Observable对象的subscribe()方法,并把一个Observer对象传给它,用来接收通知。

subscribe()方法的调用会返回一个Subscription对象,该对象具有一个unsubscribe()方法。当调用该方法时,你就会停止接收通知。

4、多播

默认情况下可观察对象会为每一个观察者创建一次新的、独立的执行。 订阅了多少次就会有多少个独立的流(next监听器会重复调用)。

多播:多播用来让可观察对象在一次执行中同时广播给多个订阅者。借助支持多播的可观察对象,你不必注册多个监听器,而是复用第一个(next)监听器,并且把值发送给各个订阅者。

// Subject,用它可以创建多播的可观察对象,也就是多个观察者共享一个订阅者函数,生产者每次发送的值,都会发送给多播中的每一个观察者!
// Subject既可以作为可观察对象使用、又可以作为观察者使用!

// 作为observable
const subject = new Subject();
const observer1 = {
    next: num => console.log("observer1.." + num)
}
const observer2 = {
    next: num => console.log("observer2.." + num)
}
// 注册两个观察者!注意,这里是注册订阅者函数而已,
// 而不是像Observable.subscribe()那样执行订阅者函数(observable订阅的时候就直接执行了)
subject.subscribe(observer1);
subject.subscribe(observer2);

// 执行(每发布一个值,两个观察者是同时收到的)
subject.next(1);
subject.next(2);
subject.next(3);

observable在订阅时,就触发发布值,然后消费值;
subject可以先订阅,等到值发布时,在消费;
const observable = of(1, 2, 3);
// 作为 observer
const subject = new Subject();

// 作为observer,注册订阅者函数而已
subject.subscribe({
	next: x => console.log(x),
});

observable.subscribe(subject); // 真正订阅数据,本来是要传订阅函数进去的,现在传subject就行了