学习Reactive Extensions(Rx) --- 笔记1
代码片段:
Observable.Interval(TimeSpan.FromSeconds(0.25))//创建了一个每0.25秒发出递增数字的Observable
.Do(x =>
{
//Do操作符的作用,它允许在不修改观察者的情况下添加副作用,比如打印日志
Console.WriteLine(x);//用Do操作处理的OnNext事件:打印每个值
})
.Subscribe();//添加订阅
//调用Subscribe()实际上是创建了一个空的观察者,只是启动了数据流。
//这里的订阅者是隐式创建的,由Rx框架生成的观察者实例,这个观察者会接收事件,
//但因为Subscribe没有参数,所以除了Do中的操作,不会有其他处理
//Subscribe()即使没有参数,也会触发Observable开始发射数据,因为订阅本身就是启动数据流的信号
运行效果如下图,数字一直不断打印:
**解释说明 **
1、Observable.Interval(TimeSpan.FromSeconds(0.25))
这会创建一个Observable(可观察序列),每隔0.25秒自动发出一个从0开始递增的long型数字值,
相当于创建了一个每秒触发4次的计数器。
2、Do(x=>{Console.WriteLine(x);})
Do操作符用于在数据流中添加“副作用”————不修改数据流,只执行额外操作。
这里的作用是将每个发出的数值x通过Console.WriteLine打印到控制台。
注意:
如果缺少订阅,那么Do操作就不会执行。
在Rx中,Observable需要被订阅(Subscribe)才会激活数据流。
在Rx(Reactive Extensions)中,.Subscribe()的订阅者(订阅者)是由Rx框架隐式创建的观察者(Observer)。
当调用 .Subscribe() 时,Rx 会自动生成一个默认的观察者实例(即使没有显式传递任何回调函数)。这个观察者的作用是:
(1)、启动数据流:触发 Observable 开始发射数据。
(2)、处理事件:接收 OnNext、OnError、OnCompleted 事件(如果没有自定义处理,默认会忽略这些事件)。
.Subscribe(); // 隐式创建了一个空的观察者
Do和Subscribe的关系
Do 操作符:
**作用**:在数据流中添加“副作用”(例如打印日志、记录状态)。
**不修改数据流**:它不会改变事件的传递,只是“偷看”数据流。
**与订阅无关**:Do 不会启动数据流,只是定义了一个中间操作。
Subscribe 方法:
**作用**:触发订阅行为,激活 Observable 并开始接收事件。
**必需调用**:没有 Subscribe,Observable 永远不会开始发射数据。
.Do(x => Console.WriteLine(x)) // 定义副作用(打印)
.Subscribe(); // 启动数据流
即使 **Subscribe() 没有参数,Do **中定义的副作用仍会执行,因为 Do 是在数据流中插入的操作,与订阅者无关。
如果要显示传递一个观察者,最初的代码等价于:
var observable = Observable.Interval(TimeSpan.FromSeconds(0.25))
.Do(x => Console.WriteLine(x));
observable.Subscribe(
x => { /* 默认空实现(不处理 OnNext) */ },
ex => { /* 默认空实现(不处理 OnError) */ },
() => { /* 默认空实现(不处理 OnCompleted) */ }
);
此时:
Do 负责打印 OnNext 事件。
Subscribe 的默认空观察者仅激活数据流,不做其他操作。
总结
Observable.Interval :创建数据流(不发射数据,直到被订阅)。
Do :定义副作用(例如打印),但不启动数据流。
Subscribe() :隐式创建观察者,启动数据流,使 Observable 开始工作。
常见问题
1、为什么需要 Subscribe 才能启动数据流?
Rx 的设计遵循“冷观察者”(Cold Observable)模式:只有在订阅后,Observable 才会开始生产数据。
这种设计避免资源浪费(例如无用的计时器)。
2、如果忘记调用 Subscribe 会怎样?
数据流永远不会激活,Do 中的代码也不会执行。例如原始代码缺少 Subscribe,就不会有任何输出。
3、是否必须传递参数给 Subscribe?
不是。如果不需要处理 OnNext/OnError/OnCompleted,可以调用无参的 Subscribe()。此时 Rx 会用默认观察者激活数据流。