rxjs入门学习笔记

之前早就听说并简单看过响应式函数编程,但并没有仔细的学习并写过代码练习,(其实作为一个程序员特别是跟UI打交道的程序员,挺不应该的…响应式函数编程号称是找到了解决UI编程复杂性的方法),今天抽时间学习练习一下(比较浅薄的记录,对rxjs很熟悉的人就不要看了…)。

先了解一些基本概念,
Functional programming: 函数式编程,参考维基百科链接

Reactive Programming: 响应式编程,参考维基百科链接

Functional Reactive Programming: 响应式函数编程, 参考维基百科链接
简单说就是: 函数式编程+响应式编程, 思想来自于微软。在各个语言都有其实现, OC和Swift有ReactCocoa, Java有RxJava, Javascript有Rxjs。

为什么选择Javascript来学习呢?因为我猜Javascript更有可能统一宇宙吧…

先学习一下rxjs中的一些基本概念(当然其他语言的实现中也包含这些基本概念)。

Observable
一组可被观测的值,可以用来表示未来的值或者事件
Observer
观察者,知道如何处理来自Observable的值
Subscription
订阅,表示Observable的执行,Observable只有在subscribe时才开始执行
Operators
纯函数,用来处理和转换Observable发出的事件流
Subject
既是Observer又是Observable,可以用来实现广播的功能
Schedulers
用来集中处理并发,允许我们控制订阅的执行的时机和事件通知的时机

不太想也没办法一开始就把所有概念理解的非常清楚,在对基本的概念有了大致了解的基础上,还是动手来写点代码会更有助于理解一些。

因此考虑实现一个比较常见的业务场景来使用下rxjs: 搜索框输入文字,在输入的过程中,边输入边查询服务器的服务并显示输入提示的信息。
这个场景看似比较简单,但如果完全正确实现,还是有一些细节要考虑:
1. 监听输入框的文本变化
2. 查询服务器搜索提示服务
3. 取得结果并显示出来
4. 为了防止每次输入都去请求服务器造成浪费,需要输入以后延迟一小段时间(例如500ms)再去请求服务器
5. 请求服务器过程是异步的,在请求过程中,如果输入框内容变化了,请求结果不应该显示出来

按这些点分别讲一下实现:
1)监听输入框文本变化事件, 通过查文档,rxjs有一个fromEvent方法可以将dom事件转成Observable
2) 先用Mock的方法模拟一个服务器请求和相应的结果
3) 直接显示结果
4) 仔细查了下,在Operator里有一个throttleTime可以实现延迟执行,在规定时间内只执行1次的需求
5) 请求结果带请求时的输入参数,如果请求时输入参数和返回时输入参数有了变化,则不更新搜索提示

写的比较简单,但实际还是摸索了很久/(ㄒoㄒ)/

源码如下:


<div> <br /> <span>{{recommendResult}}</span> </div> import { fromEvent, asyncScheduler } from 'rxjs'; import { throttleTime, map, switchMap } from 'rxjs/operators'; export default { name: 'HelloWorld', data() { return { recommendResult: '', }; }, mounted() { function mockApiCall(text) { return new Promise((resolve) =&gt; { setTimeout(() =&gt; { resolve({ query: text, recommend: `recommend of ${text}`, }); }, 300); }); } fromEvent(this.$refs.input, 'input') .pipe( throttleTime(500, asyncScheduler, { leading: false, trailing: true }), map(() =&gt; this.$refs.input.value), switchMap(text =&gt; mockApiCall(text)), ) .subscribe((result) =&gt; { if (result.query === this.$refs.input.value) { this.recommendResult = result.recommend; } }); }, };

几个小坑:
1. rxjs 最新的api和之前的差不少,所以网上的一些文章(没标明版本的)不太好参考,还是看官方文档比较靠谱
2. throttleTime 如果不加参数,默认是{ leading: true, trailing: false }这样的效果就是,输入一开始就有一个事件出来,但是最终停止了是没有事件的,但我们想要的是停止的时候需要有一个事件,因此要改成{ leading: false, trailing: true }
3. mock的api请求是基于promise的接口,想融入到Observable的事件流里边,花了一番精力,理解文档,上网搜,才知道用switchMap这个Operator可以实现

看源码,核心的控制整个事件监听和响应的流程的代码一共10行左右,提到的那些小点也都满足了,整个控制流程不会散落在各个函数里边,代码还是比较清晰的,更少的代码代表着更少的bug,不过如果对rx不熟的人理解起代码来或者上手还是比较费劲的。

思考: 第4点其实有更合理的方式,应该是输入停止一小段时间(例如300ms)再去请求服务器,这样如果用户一直在快速输入,其实是不需要任何请求的,如果采用这种方式,如何用rxjs来实现呢?

注: 文中rxjs版本基于6.5.2, 主要参考自官网: rxjs官网链接