zhouqijie

概览





第一部分:继承自Linq的操作符

Siki:UniRx操作符和Linq操作符的意思基本一致,了解Linq操作符可以加深对UniRx的理解。

Where操作符

LINQ中的Where操作符和SQL中的Where作用相似。
CRE:UniRx中的Where操作符用于按条件过滤事件。

Select操作符

CRE:Linq中的Select类似SQL的Select,即选取列(字段)。
Siki:可以选择自己,也可以选择一个其他类型的变量作为结果。

Distinct操作符

CRE:Linq中的操作符用于获取不重复的元素。
Siki:UniRx的Distinct在操作List时候,除了⽀持LINQ所⽀持的两种⽅式外,还⽀持传⼊⼀个特定条件函数。

First操作符

CRE:LINQ中的First可以选择符合条件的第一个结果,无条件参数时直接选择第一个元素。
CRE:UniRx中的First用于选择第一个事件。

Last操作符

CRE:Linq中的Last操作符返回最后一个元素。
Siki:Last⽀持传⼊⼀个条件函数,⽽LINQ中的LAST只能传⼊⼀个条件⽅法。

Single操作符

LINQ中的Single:返回序列的唯一元素;如果该序列并非恰好包含一个元素,则会引发异常。
Siki:UniRx中使用Single操作符,如果Observable不是第一次发射数据,则会抛出NoSuchElementException异常。

SelectMany操作符

在LINQ中是将序列的每个元素投影到IEnumerable并将结果合并为一个序列。 Siki:⼀般在UniRx中,主要是完成Coroutine的顺序执⾏功能。

a.SelectMany(b.SelectMany(c)).Subscribe(_ => { Debug.Log("AllFinished");});

Take操作符/TakeLast操作符

LINQ中的Take操作符:从序列的开头返回指定数量的相邻元素。
Siki:在UniRx中使⽤Take操作符让你可以修改Observable的⾏为,只返回前⾯的N项数据,然后发送完成通知,忽略剩余的数据。

LINQ中的TakeLast操作符:返回序列最后几项。
CRE:UniRx类似。

Concat操作符

LINQ中的Concat:连接两个序列。

Siki:UniRx中的Concat操作符连接多个Observable的输出,就好像它们是⼀个Observable。

WhenAll操作符(LINQ-All)

LINQ中的All:确定序列中的所有元素是否都满⾜条件。
Siki:UniRx中的WhenAll判定是否Observable发射的所有数据都满⾜某个条件。

OfType操作符

LINQ中的OfType:根据指定类型筛选IEnumerable的元素。
CRE:UniRx中的OfType类似。

Cast操作符

LINQ中的Cast:将IEnumerable的元素强制转换为指定的类型。
CRE:UniRx中的Cast类似。

GroupBy操作符

LINQ中的GroupBy:对序列中的元素进⾏分组。
CRE:UniRx的GroupBy类似。

Skip操作符

LINQ中的Skip操作符:跳过序列中指定数量的元素,然后返回剩余的元素。
CRE:UniRx的Skip类似,跳过前n个事件。

TakeWhile操作符/SkipWhile操作符

LINQ中的TakeWhile:如果指定的条件为true,则返回序列中的元素,然后跳过剩余的元素。
CRE:UniRx的TakeWhile类似。

LINQ中的SkipWhile:如果指定的条件为 true,则跳过序列中的元素,然后返回剩余的元素。
CRE:UniRx的SkipWhile类似。

Zip操作符(.NET4)

LINQ中的Zip:将指定函数应⽤于两个序列的对应元素,以⽣成结果序列。
CRE:UniRx的Zip类似。

int[] ids = { 1, 2, 3 };
string[] names = { "A", "B", "C" };
var result = ids.Zip(names, (first, second) => "id: " + first + " name:" + second);

Aggregate操作符

LINQ:对序列应用累加器函数。 将指定的种子值用作累加器的初始值,并使用指定的函数选择结果值。
CRE:UniRx类似。

ToArray/ToList操作符

LINQ:从IEnumerable中创建数组/List。 CRE:可以从IObservable创建数组或者List。

Range操作符

LINQ中的Range操作符:⽣成指定范围内的整数的序列。
CRE:UniRx的Range类似。

var squares = Observable.Range(0, 99).Select(x => x * x)
squares.Subscribe(square => Debug.Log(square));  

Repeat操作符

LINQ中的Repeat:生成包含一个重复值的序列。
CRE:UniRx类似。

Empty操作符

LINQ:返回具有指定类型参数的空IEnumerable。 CRE:UniRx类似。





第二部分:继承自Rx.Net的操作符

Interval

Observable.Interval(TimeSpan.FromSeconds(1))
    .Subscribe(seconds =>
    {
        Debug.LogFormat("当前时间:{0} s", seconds);
    })
    .AddTo(this);

TakeUntil

当第二个Observable发射了一项数据或者终止时,丢弃原始Observable发射的任何数据。

this.UpdateAsObservable()
    .TakeUntil(Observable.EveryUpdate().Where(_=>Input.GetMouseButtonDown(0)))
    .Subscribe(_ =>
    {
        Debug.Log(123);
    });
//点击鼠标左键后停止输出

SkipUntil

丢弃原始Observable发射的数据,直到第二个Observable发射了一项数据。

var clickStream = this.UpdateAsObservable().Where(_ => Input.GetMouseButtonDown(0));

// 监听
this.UpdateAsObservable()
    .SkipUntil(clickStream)
    .Subscribe(_ => Debug.Log("123"));  

//点击鼠标左键后开始持续输出

Buffer

Observable.Interval(TimeSpan.FromSeconds(1.0f))
    .Buffer(TimeSpan.FromSeconds(3.0f))
    .Subscribe(_ => 
    { 
        Debug.LogFormat("currentTime:{0}", DateTime.Now.Second); 
    })
    .AddTo(this); 

//输出
// 11
// 14
// 17
//...

Throttle

仅在过了⼀段指定的时间还没发射数据时才发射⼀个数据。
Cre:Throttle可以用于QTE或者一串连击事件的监听。

Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0))
    .Throttle(TimeSpan.FromSeconds(1))
    .Subscribe(_ => Debug.Log("⼀秒过后")); 
//点击⿏标后 1 秒内不在点击则输出,如果有点击则中重新计时 1 秒再输出。

Delay

Observable.EveryUpdate()
    .Where(_ => Input.GetMouseButtonDown(0))
    .Delay(TimeSpan.FromSeconds(1.0f))
    .Subscribe(_ => { Debug.Log("mouse clicked"); })
    .AddTo(this);
//点击⿏标1秒之后输出,每次点击事件都是1秒之后才输出。  

Return

Observable.Return("hello")
    .Subscribe(Debug.Log);
//只执行一次。

Timer

创建一个Observable,它在给定延迟之后发射一个特殊值。

Observable.Timer(TimeSpan.FromSeconds(5.0f))
    .Subscribe(_ => { Debug.Log("after 5 seconds"); })
    .AddTo(this);
//5秒后输出。  

Sample(ThrottleLast)

“采样”Observable最近发射的数据项。

Observable.Interval(TimeSpan.FromMilliseconds(400))
    .Sample(TimeSpan.FromSeconds(1))
    .Subscribe(v => { Debug.Log(v); })
    .AddTo(this);
//输出:1、3、6、8、11...  
//如果去掉Sample语句则输出:0、1、2、3、4、5...  

Timestamp

给Observable发射的数据项附加⼀个时间戳。

Observable.Interval(TimeSpan.FromSeconds(1.0f))
    .Timestamp()
    .Subscribe(v => { Debug.Log(v); })
    .AddTo(this);
//输出:
//0@yyyy/mm/dd hh:mm:ss +xx:xx
//1@yyyy/mm/dd hh:mm:ss +xx:xx
//...

ThrottleFirst

与Throttle不同,在每个采样周期内他总是发送Observable的第一个数据而不是最后一项。

TimeInterval

将⼀个发射数据的Observable转换为发射那些数据发射时间间隔的Observable。

Observable.Interval(TimeSpan.FromMilliseconds(750))
    .TimeInterval()
    .Subscribe(timeInterval => Debug.LogFormat("{0}: {1}", timeInterval.Value, timeInterval.Interval));
//0: 00:00:00.7816660
//1: 00:00:00.7619180
//2: 00:00:00.7531140 

Defer

Defer操作符会⼀直等待直到有观察者订阅它,然后它使⽤Observable⼯⼚⽅法⽣成⼀个Observable。它对每个观察者都这样做,因此尽管每个订阅者都以为⾃⼰订阅的是同⼀个Observable,事实上每个订阅者获取的是它们⾃⼰的单独的数据序列。

Never

创建一个不发射也不终止的Observable。

Scan

Scan操作符对原始Observable发射的第⼀项数据应⽤⼀个函数,然后将那个函数的结果作为⾃⼰的第⼀项数据发射。它将函数的结果同第⼆项数据⼀起填充给这个函数来产⽣它⾃⼰的第⼆项数据。它持续进⾏这个过程来产⽣剩余的数据序列。这个操作符在某些情况下被叫做accumulator。

Observable.Range(0, 8)
    .Scan(0,(acc,currentValue)=>acc+5)
    .Subscribe(xx => { Debug.Log(xx); }); 
//输出:5、10、15、20....

Switch

Switch订阅⼀个发射多个Observables的Observable。当原始Observable发射了⼀个新的 Observable时(不是这个新的 Observable发射了⼀条数据时),它将取消订阅之前的那个Observable。

var buttonDownStream = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0));
var buttonUpStream = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonUp(0))
buttonDownStream.Select(_ =>
    {
        Debug.Log("down");
        return buttonUpStream;
    })
    .Switch()
    .Subscribe(_ => { Debug.Log("up"); });
//按下鼠标输出down,抬起之后输出up

StartWith

如果你想要⼀个Observable在发射数据之前先发射⼀个指定的数据序列,可以使⽤StartWith 操作符。(如果你想⼀个Observable发射的数据末尾追加⼀个数据序列可以使⽤Concat操作符。)

CombineLatest

当两个Observables中的任何⼀个发射了数据时,使⽤⼀个函数结合每个Observable发射的最近数据项,并且基于这个函数的结果发射数据。

Merge

CRE:简单地合并两个事件流。

Create

Create操作符从头开始创建⼀个Observable。

Observable.Create<int>(o =>
{
    o.OnNext(1);
    o.OnNext(2);
    o.OnCompleted();
    return Disposable.Create(() => Debug.Log("已取消订阅"));
}).Subscribe(xx => { Debug.Log(xx); });  

Amb

给定两个或多个Observable,它只发射最先发射数据的那个Observable的所有数据。

Timeout

如果原始Observable过了指定的⼀段时⻓没有发射任何数据,Timeout操作符会以⼀个onError通知 终⽌这个Observable。

FromEvent

将其他种类的对象和数据转换为Observable。

Observable.FromEvent(action => OnClickEvent += action, action => OnClickEvent -= action)
    .Subscribe(_ => Debug.Log("button clicked"));  

Publish

将普通的Observable转换为可连接的Observable。可连接的Observable(connectable Observable)与普通的Observable差不多,不过它并不会在被订阅时开始发射数据,⽽是直到使⽤了Connect操作符时才会开始。⽤这种⽅法,你可以在任何时候让⼀个Observable开始发射数据。

RefCount

让⼀个可连接的Observable⾏为像普通的Observable。

Replay

保证所有的观察者收到相同的数据序列,即使它们在Observable开始发射数据之后才订阅。

如果在将⼀个Observable转换为可连接的Observable之前对它使⽤Replay操作符,产⽣的这个可连接Observable将总是发射完整的数据序列给任何未来的观察者,即使那些观察者在这个Observable开始给其它观察者发射数据之后才订阅。

Connect

将一个可连接Observable开始发射数据给订阅者。

Throw

创建⼀个不发射数据以⼀个错误终⽌的Observable。

Catch

从onError通知中恢复发射数据。
Catch操作符拦截原始Observable的onError通知,将它替换为其它的数据项或数据序列,让产⽣的Observable能够正常终⽌或者根本不终⽌。

Finally

注册⼀个动作,当它产⽣的Observable终⽌之后会被调⽤,⽆论是正常还是异常终⽌。

DelaySubscription

CRE:延迟订阅。

PairWise

Observable.Range(0, 10)
    .Pairwise()
    .Subscribe(pair => Debug.Log(pair.Current + ":" + pair.Previous));
//输出:
//1:0
//2:1
//3:2
//......





第三部分:Rx独有操作符

NextFrame

DelayFrame

FrameInterval

BatchFrame

ForEachAsync

FrameTimeInterval

SampleFrame

RepeatUntilDestroy

SubscribeOnMainThread

DelayFrameSubscript

ThrotleFirstFrame

ThrotleFrame

TakeUntilDestroy

TakeUntilDisable

RepeatUntilDisable

(END)