理解观察者模式——用Angular的httpClient来解释观察者
2020/3/14 14:01:28
本文主要是介绍理解观察者模式——用Angular的httpClient来解释观察者,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
本文关键词:观察者模式。
观察者模式是什么?
观察者模式和回调函数有什么关系?
使用httpClient时,加上.subscribe有什么作用?
Angular的httpClient中如何体现观察者模式?
解决了上述问题之后,就写了这篇文章。
(这篇文章实际上是给上一篇文章填个坑...上一篇写到回调函数,却没有给出实际应用的例子。)
引入问题:httpClient
httpClient是Angular中的一个内置类,用于向后台发起Http请求、返回请求结果。用它来举例子是因为功能比较简单,易于理解。
在Angular中有这么一种写法:
// 向8080端口的helloWorld路径发起请求 httpClient.get('http://localhost:8080/helloWorld') .subscribe((data) => { console.log('请求成功'); console.log(data); }, error); }
不经意一看,这不就是简单的链式调用么?——前一个方法返回一个对象,再调用这个对象的方法,再返回对象,再调用方法...
但是仔细看,才发现:这根本就不是一个过程,而是两个过程啊!
从使用.get向后台发起请求之后,到调用.subscribe之前,这之中经历了一个后台接收数据、处理数据、返回数据的过程。
那么问题来了:挖掘机技术哪家强?前台如何知道数据什么时候返回?怎么在数据返回之后,自动执行后面的代码来打印返回数据?
观察者模式
观察者模式,顾名思义,有这样一个对象,在始终被另一个对象观察着、注视着、紧紧的盯着。
用杂志社做比喻:有一个杂志社,杂志社里有一个订阅报刊的部门,一个读者向这个部门订阅了杂志,从此以后读者日日期盼着读到自己买的杂志,而订阅部门也会在新的杂志出版之后,第一时间送到读者手里。
这就是观察者模式,它由两部分组成:
数据源 + 订阅者 = 观察者模式
数据源和订阅者之间是一对多的关系。订阅者通过某种方法,向数据源发起订阅,此后,数据源一旦发生变更,会马上通知所有的订阅者。
既然知道了原理,那么在httpClient中具体是怎么实现的呢?
我们找到源码,httpClient类的所有方法都写在里面,并且有一大堆重载:
我们拿出一个方法来看看:
/** * Constructs a `GET` request that interprets the body as a text string * and returns the response as a string value. * * @param url The endpoint URL. * @param options The HTTP options to send with the request. * * @return An `Observable` of the response, with the response body of type string. */ get(url: string, options: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: 'body'; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; }): Observable<string>;
把代码格式化一下,变成我们容易理解的方式:
可以看到get方法的必填参数是请求地址URL,还有可选参数。但这些都不重要,关键在于,普通的方法,用方法名+参数就完事了,比如:
test();
再看这个方法的最后,多出了一个: Observable<string>这是观察者的关键!这条代码的意思是:返回类型为“观察者”的对象,这个观察者携带着string类型的被观察的数据。
Observable是“可观察的”意思,声明一个方法有可观察的对象之后,这个方法的返回值就不再是一个普通变量,而是一个“观察者”对象,我们对这个对象使用.subscribe方法订阅,就可以传入函数进行回调了。
我们在控制台打印一下.get()方法的返回值:
console.log(this.httpClient.get(`http://localhost:8080/Klass/${klass.id}`));
果然是一个对象,这个对象包含了订阅数据源的功能,等到数据返回之后再使用.subscribe方法来操作返回的数据。
接下来,我们来看subscribe方法:
subscribe(observer?: PartialObserver<T>): Subscription; /** @deprecated Use an observer instead of a complete callback */ subscribe(next: null | undefined, error: null | undefined, complete: () => void): Subscription; /** @deprecated Use an observer instead of an error callback */ subscribe(next: null | undefined, error: (error: any) => void, complete?: () => void): Subscription; /** @deprecated Use an observer instead of a complete callback */ subscribe(next: (value: T) => void, error: null | undefined, complete: () => void): Subscription; subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
依然是选出一个,格式化成熟悉的形式:
可以看出,这个方法需要传入三个回调函数,分别为:
- HTTP请求执行成功后执行什么方法
- HTTP请求失败后执行什么方法
- 无论成功或失败,最后执行什么方法
所以只要把对应的方法传入,就可以了(也可以不都传入,subscribe由于有重载函数,可以处理不同的参数)。
观察者和回调函数有什么关系?
在调用.subscribe时,为什么要传入success和error两个方法?
——其实是为了代码解耦,回调函数的目的本来就是为了代码解耦。在方法A()中传入方法B()用于回调,就可以把方法A()执行之后的数据交给方法B()来操作。所以方法A()执行后的数据是不变的,具体怎么操作这个数据,就要看传进去的方法了。
同理,观察者向数据源发起订阅之后,当数据源发生变化时,把新的数据通知给订阅者。数据既然已经拿到手,怎么处理数据就是订阅者的事了,和数据源没关系了。所以在观察者模式里使用回调函数的好处在于:当处理返回值的功能发生变化时,并不用改动数据源的任何代码。
这就好比:杂志社把杂志交给客户之后,客户想不想看、什么时候看,或者想把杂志扔掉,都是客户自己的事情,和杂志社没有半毛钱的关系。
总结
数据源 + 订阅者 = 观察者模式
观察者模式,是设计模式里面最简单的,也是最好理解的一种。
笔者也处于初学阶段,以后会学到更多的设计模式。对于学习的过程来说,最大的喜悦,无非就是那种豁然开朗的感觉了,从一开始的一团浆糊到后来的融会贯通。这种喜悦,应该就是学习最大的回报吧。
这篇关于理解观察者模式——用Angular的httpClient来解释观察者的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Vite多环境配置学习:新手入门教程
- 2024-11-23实现OSS直传,前端怎么实现?-icode9专业技术文章分享
- 2024-11-22在 HTML 中怎么实现当鼠标光标悬停在按钮上时显示提示文案?-icode9专业技术文章分享
- 2024-11-22html 自带属性有哪些?-icode9专业技术文章分享
- 2024-11-21Sass教程:新手入门及初级技巧
- 2024-11-21Sass学习:初学者必备的简单教程
- 2024-11-21Elmentplus入门:新手必看指南
- 2024-11-21Sass入门:初学者的简单教程
- 2024-11-21前端页面设计教程:新手入门指南
- 2024-11-21Elmentplus教程:初学者必备指南