Observable与Subject
#介绍
首先,对象关系上,Subject是Observable的子类,相比拥有了多播的效果,使得多个订阅者订阅的对象数据是共享的,而在它下面又细分了AnonymousSubject, AsyncSubject, BehaviorSubject三个子类,分别用于处理不同场景的业务需求。
#Observable和Subject的差异
- Observable的每个订阅者之间,读取的发布数据是相对各自独立的。
- Subject的订阅者之间,是共享一个发布数据的。
#Subject的子类详情
1. BehaviorSubject
Subject的主要子类是BehaviorSubject,使用BehaviorSubject具有存储当前“值”的特性,这意味着我们始终可以直接从BehaviorSubject获取最后发出的值。
获取值一共有两种方法
- 通过访问.value属性来获取值
- 通过订阅BehaviorSubject来获取值,BehaviorSubject将直接向订阅者发出当前值。即使订阅者订阅的时间远远晚于存储的值。
import * as Rx from "rxjs";const subject = new Rx.BehaviorSubject();// 订阅对象1
subject.subscribe((data) => {console.log('Subscriber A:', data);
});
//发布新的值
subject.next(Math.random());
subject.next(Math.random());// 订阅对象2
subject.subscribe((data) => {console.log('Subscriber B:', data);
});
// 再次发布新的值
subject.next(Math.random());console.log(subject.value)// 输出日志
// Subscriber A: 0.24957144215097515
// Subscriber A: 0.8751123892486292
// Subscriber B: 0.8751123892486292
// Subscriber A: 0.1901322109907977
// Subscriber B: 0.1901322109907977
// 0.1901322109907977
- 我们首先创建一个主题并使用Subscriber A订阅它。然后,Subject将发出它的值,订阅者A将记录随机数。
- 主题发出它的下一个值。订户A将再次记录此信息
- 订阅者B从订阅主题开始。由于主题是BehaviorSubject,新订阅者将自动接收最后存储的值并记录此信息。
- 主题再次发出新值。现在,两个订阅者都将收到值并记录它们。
- 最后,我们只需访问该.value属性即可记录当前的Subjects值 ,因为它是同步的,可以不用通过订阅读取值。
最后,我发现现在已经需要在创建对象的时候赋予初始值,如下示例:
import * as Rx from "rxjs";
// 参数:初始值
const subject = new Rx.BehaviorSubject(Math.random());
2.ReplaySubject
ReplaySubject可以与BehaviorSubject相比,它可以向新订阅者发送“旧”的历史值。借此特性,我们可以用它可以记录可观察对象执行的一部分,因此存储多个旧值并将它们“重放”给新的订阅者。
创建ReplaySubject时,你可以指定要存储的值的数量以及要存储它们的时间长度。
import * as Rx from "rxjs";
// 存储2个值,这些值在新订阅之前的最后一秒执行
const subject = new Rx.ReplaySubject(2);// 开始使用订阅者A订阅主题
subject.subscribe((data) => {console.log('Subscriber A:', data);
});
// 发布三个新值
subject.next(Math.random())
subject.next(Math.random())
subject.next(Math.random())// 订阅B
subject.subscribe((data) => {console.log('Subscriber B:', data);
});
// 发布新值
subject.next(Math.random());// 输出日志
// Subscriber A: 0.3541746356538569
// Subscriber A: 0.12137498878080955
// Subscriber A: 0.531935186034298
// Subscriber B: 0.12137498878080955
// Subscriber B: 0.531935186034298
// Subscriber A: 0.6664809293975393
// Subscriber B: 0.6664809293975393
根据输出来看,订阅者A记录了三个发布值。
由于我们告诉ReplaySubject存储2个值,它将直接向订阅者B发送最后两个值,订阅者B于是只输出了最后发布的两个值。
除此之外,我们还可以指定存储值的时间,如下所示。
import * as Rx from "rxjs";
//创建ReplaySubject并指定只存储最后2个值,但不超过100毫秒
const subject = new Rx.ReplaySubject(2, 100);// 创建订阅A
subject.subscribe((data) => {console.log('Subscriber A:', data);
});
// 每隔200毫秒开始发出主题值。订阅者A将选择此项并记录主题发出的每个值
setInterval(() => subject.next(Math.random()), 200);// 创建订阅B
setTimeout(() => {subject.subscribe((data) => {console.log('Subscriber B:', data);});
}, 1000)// 输出日志
// Subscriber A: 0.44524184251927656
// Subscriber A: 0.5802631630066313
// Subscriber A: 0.9792165506699135
// Subscriber A: 0.3239616040117268
// Subscriber A: 0.6845077617520203
// Subscriber B: 0.6845077617520203
// Subscriber A: 0.41269171141525707
// Subscriber B: 0.41269171141525707
// Subscriber A: 0.8211466186035139
// Subscriber B: 0.8211466186035139
如上所示,我们开始订阅者B后,因为我们在1000毫秒后执行此操作,这意味着在开始订阅之前,主题已经发出了5个值。
这意味着在1000毫秒之后,当订阅者B开始订阅时,它将仅接收1个值,因为主体每200ms发出一次值。
3. AsyncSubject
虽然BehaviorSubject和ReplaySubject都存储值,但AsyncSubject的工作方式略有不同。AsyncSubject是一个主题变体,只有Observable执行的最后一个值才会发送给它的订阅者,并且只有在执行完成时才会发送.
import * as Rx from "rxjs";
// 创建了AsyncSubject
const subject = new Rx.AsyncSubject();// 创建订阅A
subject.subscribe((data) => {console.log('Subscriber A:', data);
});subject.next(Math.random())
subject.next(Math.random())
subject.next(Math.random())// 创建订阅B
subject.subscribe((data) => {console.log('Subscriber B:', data);
});subject.next(Math.random());
subject.complete();// 输出日志
// Subscriber A: 0.4447275989704571
// Subscriber B: 0.4447275989704571
如上我们能够观察到,A并没有输出发布的前三个值,是因为只有当订阅对象complete完成后,才会将值发送给订阅者。
#结论
BehaviorSubject,ReplaySubject和AsyncSubject不仅可以像使用普通Subject一样用于多播,而且它们在不同场景中各自有具有非常方便的特性,我们可以结合业务场景和需求具体使用。
PS: 如上教程多为译文,原文地址如下(可能需要VPN才能访问):
原文:https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0
Observable与Subject相关推荐
- RXJS 中 Observable 和 Subject
1.消费者 决定何时从数据 生产者 中接收数据,生产者本身不知道数据何时会被传递给消费者,函数本身不知道何时会被调用,只有调用函数的人才知道. 2.生产者 决定何时将数据发送给 消费者, 消费者不知道 ...
- Subject 与 Observable 的区别
原文链接:http://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/ In order to under ...
- java subject类_RxJava 常见误区(一):过度使用 Subject
准备写这篇文章的时候看了下 RxJava 在 Github 上已经 12000+ 个 star 了,可见火爆程度,自己使用 RxJava 也已经有一小段时间.最初是在社区对 RxJava 一片赞扬之声 ...
- Rxjs Observable
创建Observable: Rx.Observable.create 是 Observable 构造函数的别名,它接收一个参数:subscribe 函数. 例子:每秒推送一个"Hi" ...
- RxJS 核心概念之Subject
本文出处:https://segmentfault.com/a/1190000005069851,我做了一部分修改 我们在接触到RxJS的时候,不免会有点晕头转向的感觉,对于什么是Subject,什么 ...
- redux rxjs_可观察的RxJS和Redux入门指南
redux rxjs Redux-Observable is an RxJS-based middleware for Redux that allows developers to work wit ...
- RxJava 和 RxAndroid 一 (基础)
1.RxJava 项目地址 https://github.com/ReactiveX/RxJava 2.RxAndroid 项目地址 https://github.com/ReactiveX/R ...
- java品酒会,我学 rxjava 2(3)- 热发射
这篇文章离上一篇文章有些时日了,概因最难心情大大的不好,非常不爽. 为啥我会专门写一下热发射呢,因为 RxBus 就是使用 RxJava 的热发射(Subject)实现的,但是呢我的出发点不同,我是因 ...
- java jdk 观察者模式_java观察者模式实现和java观察者模式演化
简单的观察者模式实现 import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; impo ...
- Rxjs 的一些学习笔记
源自观察者-发布者设计模式: 观察者注册于 Subject 上,每当 subject 状态发生变化时,通知观察者. RxJs 里的 Observable 就是 Subject: 管道:连接 Obser ...
最新文章
- 【怎样写代码】工厂三兄弟之工厂方法模式(一):问题案例
- 图像滤波常用算法实现及原理解析
- 关于主机的思维导图_几张思维导图,让你清楚的知道ip地址怎么回事?
- <DependencyManagement>记录
- C# ASP.NET MVC HtmlHelper用法大全
- 一层循环时间复杂度_数据结构与算法系列——时间、空间复杂度
- ELK --- Grok正则过滤Linux系统登录日志
- Hibernate的导入和逆向工程生成JavaBean
- Memory Cleaner for Mac(内存清理工具)最新版
- 60、在Visual Studio 2019 环境下,使用C#调用C++生成的dll实现yolov5的图片检测
- Kettle 添加备注
- php 漏洞扫描,10个最佳PHP代码安全扫描程序来查找漏洞
- XP 操作系统安全防范
- FPGA数字系统设计(9)——信号产生
- 求阶乘问题c语言编程,求阶乘问题
- 用libpcap分析CAIDA的网络流量文件的猝发性
- android 选择答题功能,Android实现简单的答题系统
- 百度,你是神一样的搜索引擎
- java 静态数组_java(四)创建静态数组
- 计算机基础教学改革申报书,混合教学试点课程改革项目申报书-《计算机文化基础》...