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,表示受保护权限,体现在继承,即子类可以 ...
随机推荐
- X86汇编快速入门
http://www.cnblogs.com/YukiJohnson/archive/2012/10/27/2741836.html
- bzoj1558
好题,初看以为只要差分然后维护相同的段数目但是请注意下面的情况2 3 5 8 9 1 2 3 4 这显然答案是3而不是4因此我们还要再维护ld,rd表示左右单独的段长度和s表示不包括左右单独的段,中间 ...
- BZOJ1345: [Baltic2007]序列问题Sequence
1345: [Baltic2007]序列问题Sequence Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 556 Solved: 274[Submi ...
- 【canvas】伸缩 / 剪裁 / 文本 / 阴影 / 填充图案 / 填充渐变
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...
- 如何修复在Microsoft Azure中“虚拟机防火墙打开,关闭RDP的连接端口”问题
注:下列步骤并不一定适用所有场景,提供思路,请灵活应用 我们在使用Microsoft Azure 中Windows 虚拟机,有时会发生错误打开防火墙或一些管家软件错误的关闭了"远程桌面 ...
- 转载--C语言运算符优先级和口诀
转载:http://www.cnblogs.com/zhanglong0426/archive/2010/10/06/1844700.html 一共有十五个优先级: 1 () [] . -& ...
- JavaScript高级程序设计42.pdf
IE中的事件对象 要访问IE中的event对象有几种不同的方式,取决于指定事件处理程序的方法.在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在 wondow.e ...
- 【解决】笔记本发射WiFi
这个百度一下一大堆 .. 不过还是希望自己总结一发适合自己的 (*^__^*) 废话不多说,开始 基于几个bat (1)CreateWlan.bat netsh wlan set hostednet ...
- books
<<learning opencv>>, 布拉德斯基 (Bradski.G.) (作者), 克勒 (Kaehler.A.) (作者), 这本书一定要第二版的,因为第二版 ...
- spider爬站极度损耗站点流量
或许部分站长遇到过这样的情况,Baiduspider对一个网站的抓取频率要远高于新内容产出速度,造成了N多的流量被蜘蛛占用. 这样的情况一般是针对小站,因为大站访问量很大,蜘蛛对服务器的频繁访问不会有 ...