ReactiveCocoa 中signal(operation) then与doNext的区别
贴源码:
doNext:实现的主要源代码
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
return [self subscribeNext:^(id x) {
block(x);
[subscriber sendNext:x];
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
[subscriber sendCompleted];
}];
}] setNameWithFormat:@"[%@] -doNext:", self.name];
then:实现的主要源代码
1、
- (RACSignal *)then:(RACSignal * (^)(void))block {
NSCParameterAssert(block != nil);
return [[[self
ignoreValues]
concat:[RACSignal defer:block]]
setNameWithFormat:@"[%@] -then:", self.name];
}
2、
- (RACSignal *)ignoreValues {
return [[self filter:^(id _) {
return NO;
}] setNameWithFormat:@"[%@] -ignoreValues", self.name];
}
3、
- (instancetype)filter:(BOOL (^)(id value))block {
NSCParameterAssert(block != nil);
Class class = self.class;
return [[self flattenMap:^ id (id value) {
if (block(value)) {
return [class return:value];
} else {
return class.empty;
}
}] setNameWithFormat:@"[%@] -filter:", self.name];
}
从上面doNext与then的代码比较
从实现上看有几点:
a、doNext是在当前信号执行的任务完成后,将当前任务的结果传递给新的signal,而then:则是执行完后不会把当前的singal的结果网下传,而是生成了一个empty这个signal接着让这个empty signal来处理接下来的事。(在信号本身订阅完后处理接下来的操作)
then是直接创建一个signal并让这个singal来转发当前消息执行后的结果, doNext到最后是flattenMap,flattenMap则是通过bind的方式来实现的,而bind的方法中有介绍其功能要求(处理完之前的订阅后生成一个empty信号然后在empty信号中执行接下来的操作。):
/*
* -bind: should:
*
* 1. Subscribe to the original signal of values.
* 2. Any time the original signal sends a value, transform it using the binding block.
* 3. If the binding block returns a signal, subscribe to it, and pass all of its values through to the subscriber as they're received.
* 4. If the binding block asks the bind to terminate, complete the _original_ signal.
* 5. When _all_ signals complete, send completed to the subscriber.
*
* If any signal sends an error at any point, send that to the subscriber.
*/
bind:其中2,3两点比较特别:
在任一时刻元信号收到一个处理值的时候bindblock会做一个转换处理;
bind将一个signal作为一个bindblock中的一个返回值并且订阅这个signal;
c、资源释放角度:
doNext:RACCompoundDisposable *disposable add RACDisposable *schedulingDisposable
then:RACCompoundDisposable *disposable add RACSerialDisposable *selfDisposable
d、使用doNext和then:
resetBtn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
@strongify(self)
RACSignal *signal = [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}] doNext:^(id x) {
NSLog(@"next");
}]doNext:^(id x) {
NSLog(@"next1");
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"then");
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}];
}];
return signal;
// }];
print:
next
next1
then
resetBtn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
@strongify(self)
RACSignal *signal = [[[[RACSignal empty] doNext:^(id x) {
NSLog(@"next");
}]doNext:^(id x) {
NSLog(@"next1");
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"then");
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}];
}];
return signal;
// }];
}] ;
print:
then
then 执行的时候会忽略之前一个信号的结果,sendNext则会保留结果传给下个信号。
这样如果通过doNext:执行的话,如果执行的信号结果是一个empty那么doNext是不能够执行下去的。
而then的之前执行是在调用 ignoreValues 创建一个新的信号来接着执行,所以then能够确保下一步执行
提一下ignoreValues,ignoreValues这个方法最终实现是落在bind signal方法上,而bind这个方法实际上是一个串,通过里面的addSignal和completeBlock来完成。也就是说可以在doNext执行完之前都是信号依赖信号的形式,但是这种信号依赖机制不能够确保传出的不是empty信号,所以这种方式有可能会中断
也就是说then并不会把doNext的操作给忽略掉,只会把doNext的传出参数给忽略,同时doNext不能处理前一个signal为empty的情况,而then不管前一个signal是否是空的都可以接着执行
最后再看一下then和doNext的方法说明
then:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008400 }
span.s1 { }
/// Ignores all `next`s from the receiver, waits for the receiver to complete,
/// then subscribes to a new signal.
doNext:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008400 }
span.s1 { }
/// Do the given block on `next`. This should be used to inject side effects into
/// the signal.
前者忽略接收者的消息,并等待接收者执行完后,再订阅一个新的信号。
后者是将一个block作为副作用注入到signal中。
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 }
span.s1 { }
2017-01-09 17:26:23.355 HXViewDataBinding[2330:1268857] <RACDynamicSignal: 0x6000004269e0> name:
2017-01-09 17:26:23.355 HXViewDataBinding[2330:1268857] <RACDynamicSignal: 0x6180002241a0> name:
可以看到side effect其实也是通过createSignal的形式来完成的,只是在createsignal中完成了当前消息的转发并把消息结果给新的signal并让新的signal来做接下来的事
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #31595d }
span.s1 { color: #ba2da2 }
span.s2 { }
span.s3 { color: #4f8187 }
span.s4 { color: #31595d }
span.s5 { color: #703daa }
span.s6 { color: #000000 }
span.s7 { color: #d12f1b }
span.Apple-tab-span { white-space: pre }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #78492a }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; min-height: 13.0px }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #ba2da2 }
p.p5 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #31595d }
span.s1 { }
span.s2 { color: #4f8187 }
span.s3 { color: #ba2da2 }
span.s4 { color: #000000 }
span.s5 { color: #31595d }
span.s6 { color: #d12f1b }
span.Apple-tab-span { white-space: pre }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #ba2da2 }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #d12f1b }
span.s1 { }
span.s2 { color: #4f8187 }
span.s3 { color: #ba2da2 }
span.s4 { color: #31595d }
span.s5 { color: #000000 }
span.Apple-tab-span { white-space: pre }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #78492a }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; min-height: 13.0px }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #31595d }
span.s1 { }
span.s2 { color: #ba2da2 }
span.s3 { color: #000000 }
span.s4 { color: #3e1e81 }
span.s5 { color: #31595d }
span.s6 { color: #d12f1b }
span.s7 { color: #4f8187 }
span.Apple-tab-span { white-space: pre }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008400 }
span.s1 { }
span.Apple-tab-span { white-space: pre }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 }
span.s1 { }
ReactiveCocoa 中signal(operation) then与doNext的区别的更多相关文章
- ReactiveCocoa 中 RACSignal 是怎样发送信号
前言 ReactiveCocoa是一个(第一个?)将函数响应式编程范例带入Objective-C的开源库.ReactiveCocoa是由Josh Abernathy和Justin Spahr-Summ ...
- ReactiveCocoa 中 RACSignal 是如何发送信号的
https://juejin.im/post/5829f4c3570c350063c436ac 前言 ReactiveCocoa是一个(第一个?)将函数响应式编程范例带入Objective-C的开源库 ...
- PHP中new static()与new self()的区别异同分析
本文实例讲述了PHP中new static()与new self()的区别异同,相信对于大家学习PHP程序设计能够带来一定的帮助. 问题的起因是本地搭建一个站.发现用PHP 5.2 搭建不起来,站PH ...
- ScheduledExecutorService中scheduleAtFixedRate方法与scheduleWithFixedDelay方法的区别
ScheduledExecutorService中scheduleAtFixedRate方法与scheduleWithFixedDelay方法的区别 ScheduledThreadPoolExecut ...
- [转]ThinkPHP中实例化对象M()和D()的区别,select和find的区别
1.ThinkPHP中实例化对象M()和D()的区别 在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法实例化模型无需用户为每个数据表定义模型类,如果D方法没有找到定义的模型类,则会 ...
- angularjs中provider,factory,service的区别和用法
angularjs中provider,factory,service的区别和用法 都能提供service,但是又有差别 service 第一次被注入时实例化,只实例化一次,整个应用的生命周期中是个单例 ...
- 正则表达式中的exec和match方法的区别
正则表达式中的exec和match方法的区别 字符串的正则方法有:match().replace().search().split() 正则对象的方法有:exec().test() 1.match m ...
- JOIN关联表中ON,WHERE后面跟条件的区别
select * from td left join (select case_id as sup_case_id , count(*) supervise_number from td_kcdc ...
- Java中public,private,protected,和默认的区别
Java中public,private,protected,和默认的区别 1.private修饰词,表示成员是私有的,只有自身可以访问: 2.protected,表示受保护权限,体现在继承,即子类可以 ...
随机推荐
- C++构造函数的自动调用(调用一个父类的构造函数,有显性调用最好,否则就默认调用无参数的构造函数)——哲学思想:不调用怎么初始化父类的成员数据和VMT?
我总是记不住构造函数的特点,关键还是没有领会那个哲学思想:父类的构造函数一方面要初始化它自己的成员数据,另一方面也要建立它自己的VMT呀!心里默念一百遍:一定调用父类构造函数,一定调用父类构造函数,一 ...
- JavaScript用JQuery呼叫Server端方法
准备好Server端的方法 [System.Web.Services.WebMethod] public static string VeryUserName(string name) { strin ...
- POJ_3662_Telephone_Lines_(二分+最短路)
描述 http://poj.org/problem?id=3662 给一张图,要将1与n连起来.可以有k条边免费,其他边自费,付费的值为所有自费边中最大的值.求最小付费. Telephone Line ...
- 迷宫城堡--HDOJ 1269(Tarjan)
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- MD5Helper辅助类
DES加密和解密 public class MD5Helper { ///DES加密 ///sKey public string MD5Encrypt(string pToEncrypt, strin ...
- Bootstrap框架中的字形图标的理解
最近项目中准备使用 Bootstrap 框架,看中了Ace Admin 这套皮肤,看其代码的时候,发现使用了字形图标.下面内容来源于网络,根据自己对新知识的学习曲线重新整合了一下: 一,字形图标的定义 ...
- Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对
题目:http://codevs.cn/problem/3286/ 3286 火柴排队 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : ...
- make it clear how to use const in C++
1.first of all,take a lookup on the left side of keyword const.If there is something(type or pointer ...
- 容联云通讯_提供网络通话、视频通话、视频会议、云呼叫中心、IM等融合通讯能力开放平台。
容联云通讯_提供网络通话.视频通话.视频会议.云呼叫中心.IM等融合通讯能力开放平台. undefined
- weekend110(Hadoop)的 第三天笔记
(2015年1月17日) 课程目录 01-hdfs源码跟踪之打开输入流 02-hdfs源码跟踪之打开输入流总结 03-mapreduce介绍及wordcount 04-wordcount的编写和提交集 ...