前置知识点:
- pipe 方法: 它最直观的好处是 链式调用 ,另一个是可以用来 划分逻辑 ,在异步的场景中还可以做流程控制(串行、并行、竞速等等)。在rxjs中主要用于组合多个操作符,可以将一系列操作符作为参数传递给 pipe 方法,这些操作符将 依次 对数据流进行处理。这里的依次很关键,也代表着pipe()中组合的这么几个操作符的执行顺序就是从开始一直到结束的,其中的数据会同流水线一般在各个操作符中进行传递。上一个操作符把数据处理好了,会自动地把这个处理好的数据送给下一个操作符接收,基于这个在上一步处理过的数据再进行进一步的加工,如此往复,直到执行到最后一个操作符为止。 observeable.pipe( operator1(), operator2(), operator3(), operator3(), )->operator1 将接收 observable,对其执行操作并发出 observable。 从 operator1 发出的 observable 被传递给 operator2 作为输入(通过其余的运算符以此类推)。
- RxJS:通过提供一种 统一的方式 来处理异步和基于事件的程序。这种统一的方式就是基于它的核心思想: 将一切都视为随时间变化的数据流 ,从而能够用更加函数式和响应式的方式来处理复杂的数据处理问题。实际实现的时候,其实就是把所有的数据流、事件全都转成 Observable ,然后再在这个 Observable 的基础上进行订阅消息,实现对其发布的数据的处理。
- 观察者模式(Observer Pattern):是一种设计模式,其中一个对象(称为“主题”或“可观察对象”)维护一组观察者,当该对象状态变化时,会自动通知所有观察者。
- Observables(可观察对象):在
RxJS
中,Observables就是这样的“主题”。它代表了一个可观察的数据流或异步事件流。 - Observers(观察者):观察者是一个包含回调函数集合的对象,这些函数决定了如何响应Observable发送的数据或事件。
- 订阅(Subscribe):观察者通过“订阅”Observable来接收数据和通知。当Observable发出数据时,会调用观察者的回调函数(例如:
next, error, complete
)。简写:observable.subscribe(x => console.log('Observer got a next value: ' + x)); - Observable 的懒加载:这表示 Observable 不会在创建时立即开始工作,而是在被订阅(
subscribe
)时才开始执行 。当你创建一个 Observable 实例时,你仅仅是 定义了一个数据流和如何生成这些数据的规则 。此时,数据流并不会立即开始。只有当 Observable 被某个观察者订阅时,定义在 Observable 构造函数中的函数(订阅函数)才会 被执行 。这个函数负责产生数据并通过next
,error
, 和complete
方法发送给观察者。每当有新的订阅发生时,Observable 会从头开始执行其定义的逻辑。这意味着每个订阅者都有自己的数据流实例,互不影响。 - Observable的 创建 和 使用 :对应着 消息发布 和 消息订阅 两个过程。在创建observable实例的时候,可以通过这个对象内部的next方法进行消息的发布。这个消息发布的内容可以是任何东西,可以是事件、具体的值、Promise等。
- 数据流与操作符:在rxjs中,创建一个数据流之后并不是直接通过subscribe接上一个Observer,而是先对这个数据流做一系列处理,然后才交给Observer的。比如说一个管道,数据从一个管道或多个管道流入,而管道中可能有多个交叉管道或管道有小有大,对数据进行过滤、抛弃掉了、数据来自多个数据源,最后Observer只需要处理能够走到终点的数据。组成数据管道的元素就是操作符。
- 回压概念:一个传输管道如果管径变小了就会造成流动上游的淤积,因为变小的管道容不下当前水流的容量导致回压,如果在向服务器请求的场景下出现这种情况,就会导致数据响应回来非常慢。所以rxjs提供了一些操作符控制这个回压问题,分为有损回压控制(也就是下文的过滤类操作符,丢掉一点数据以达到当前数据能轻松通过)和无损回压控制(转化类操作符,把数据缓存起来,当时机合适时,把缓存的数据汇聚到一个数组或者Observable对象传给下游(也就是吐出数据))。
一、组合(合并多个Observable对象,然后一次性订阅)
- withLatestFrom:只要源 Observable 发出一个值,它就会 使用该值加上其他输入的最新值来计算公式 可观察对象,然后发出该公式的输出。
const source1$ = of(100, 200, 300, 400, 500); const source2$ = of(1, 2, 3, 4, 5); source1$.pipe(withLatestFrom(source2$, (a, b) => a + b)).subscribe(console.log); // 105 205 305 405 505
- switchAll:新的 observable 送出后直接处理新的 observable 不管前一个 observable 是否完成,每当有新的 observable 送出就会直接把旧的 observable 退订(unsubscribe),永远只处理最新的 observable!
- concatAll:处理完前一个 observable 才会在处理下一个 observable。依次按顺序执行一个个observable 。
- combineLatest:从所有输入Observable对象中拿最后一次产生的数据(最新数据),然后把这些数据组合起来传给下游。注意地,combineLatest直到每个 observable 都至少发出一个值后才会发出初始值。它与zip很相似,combineLatest一开始也会等待每个子流都发射完一次数据,但是在合并时,如果子流1在等待其他流发射数据期间又发射了新数据,则使用子流最新发射的数据进行合并,之后每当有某个流发射新数据,不再等待其他流同步发射数据,而是使用其他流之前的最近一次数据进行合并。
const a = interval(1000).pipe( take(2)//有0,1 ); const b = interval(1000).pipe( delay(1000),take(2)//有0,1 ); const c = interval(1000).pipe( delay(3000), take(5)//有 0,1,2,3,4 ); combineLatest会等待每个子流都发射完一次数据,返回第一次数据.