RAC

iOS:RAC进阶之冷热信号

2017-12-13  本文已影响16人  ForC

前言

之前我分析了一下源码并且用自己理解的伪代码来实现了这种信号简单的传递流程,并且在说到subject父子的时候我们留下了一个小疑问,的回掉触发时机是在订阅的时候,这样的操作会导致创建时候的didscriberblock被调用好几次,所以引发了人们对于signal优化的思考。

冷信号&热信号

冷信号和热信号的概念我第一次为了加深自己的印象在一片文章中,文章中只是解释了表面意思,个人认为没有考虑到本质。后来发现了美团大众点评技术团队的文章,第一次看的时候是在没有看任何源码的情况下看的,当时真的是一脸懵逼,后来看了下基本的源码重新看了下他们的文章,就觉得通俗易懂了。
(更新一下,我的racsignal的文章中说到了是rac作者创建出的冷热信号概念是不对的,他只是在文章中说出了signal对部分副作用的影响,作者只提到了副作用的概念,冷热信号概念来自.NET的RX)

 RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
       [[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{
            [subscriber sendNext:@"1"];
            
            [subscriber sendNext:@"2"];
        }];

        return nil;
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"subscriber1: %@", x);
    }];
    [signal subscribeNext:^(id x) {
        NSLog(@"subscriber2: %@", x);
    }];

控制台打印:
01:02:53.220464+0800 RACOne[52411:2578142] subscriber1: 1
01:02:53.220684+0800 RACOne[52411:2578142] subscriber1: 2
01:02:53.220863+0800 RACOne[52411:2578142] subscriber2: 1
01:02:53.221321+0800 RACOne[52411:2578142] subscriber2: 2

可以看出他的确完全符合冷信号的概念。首先订阅是这个发送的触发时机,只有一个block订阅了他才会发送信号并且产生订阅回掉。这一系列也解释了为什么只有订阅了才会发送信号的原因。其次发送信号都是在订阅时候调用的而订阅者单一单线程操作所以才会执行完第一个订阅者在执行第二个订阅者。

  1. RacSubject父子是热信号。
    注意一下这里为什么racreplaysubject也是热信号,虽然他们也是订阅了才会发送信号,但是他们的关注点是时间这条线,支持多订阅者同时发送,而signal关注的是订阅这条线,单订阅者订阅
    实验如下:
 RACSubject *subject = [RACSubject subject];
    RACReplaySubject *replaySubject = [RACReplaySubject subject];
    
    [subject sendNext:@"1"];
    [replaySubject sendNext:@"1"];
    
    [[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{
        [subject sendNext:@"2"];
        [replaySubject sendNext:@"2"];
    }];
    
    [subject subscribeNext:^(id x) {
         NSLog(@"subscriber1: %@", x);
    }];
    
    [subject subscribeNext:^(id x) {
         NSLog(@"subscriber2: %@", x);
    }];
    
    [replaySubject subscribeNext:^(id x) {
         NSLog(@"Replaysubscriber1: %@", x);
    }];
    
    [replaySubject subscribeNext:^(id x) {
         NSLog(@"Replaysubscriber2: %@", x);
    }];

控制台:
01:27:03.229905+0800 RACOne[52618:2590686] Replaysubscriber1: 1
01:27:03.230147+0800 RACOne[52618:2590686] Replaysubscriber2: 1
01:27:04.230362+0800 RACOne[52618:2590686] subscriber1: 2
01:27:04.230538+0800 RACOne[52618:2590686] subscriber2: 2
01:27:04.230755+0800 RACOne[52618:2590686] Replaysubscriber1: 2
01:27:04.230869+0800 RACOne[52618:2590686] Replaysubscriber2: 2

副作用

// racSiganl创建时对于副作用的阐述
Note:** The `didSubscribe` block is called every time a new subscriber
subscribes. Any side effects within the block will thus execute once for each
subscription, not necessarily on one thread, and possibly even
simultaneously!

rac是一套基于cocoa的FRP框架,FRP又称之为函数式响应编程,既然说到函数,假如是纯函数,外部传入只在函数中有改变而不对外部做出修改,但是针对于OOP中肯定包含副作用的地方。具体副作用是什么,产生在哪:

那么在编程中,这些场景基本都是编程中常见的,就是你用户点到了哪里触发了事件都属于副作用。可以说在日常编程中,副作用基本都存在,也可以这么说我们的编程就是为了产生副作用。

那么如何才能避免副作用呢?副作用又会在什么场景发挥出他们邪恶的一面呢?冷热信号和副作用有什么关系呢?

技术参考美团点评团队:https://tech.meituan.com/ 归档的2015年几期
上一篇 下一篇

猜你喜欢

热点阅读