之前一篇文章ReactiveCocoa的bind源码理解对flattenMap的理解还是差一些,这里将flattenMap的流程用自然语言描述一遍,加深理解。
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[self httpRequest:@"Post" param:@{@"commandKey":@"hello world!"} completion:^(id response) {
[subscriber sendNext:@"success!"];
[subscriber sendCompleted];
}];
return nil;
}];
RACSignal *return_signal = [signal flattenMap:^RACStream *(id value) {
return [RACSignal empty];
}];
上述代码signal称为源信号。
订阅return_signal的流程如下:
1> flattenMap返回一个信号return_signal(由bind创建,参考ReactiveCocoa的bind源码理解);
2> flattenMap的返回信号return_signal被订阅时,执行return_signal的didSubscribe;
3> 执行return_signal的didSubscribe时,会订阅源信号signal,因此源信号的didSubscribe会执行;
4> 当源信号sendNext时,flattenMap的参数block会执行,会得到flattenMap的block执行的返回信号block_return_signal;
5> addSignal(block_return_signal)会继续订阅block_return_signal,订阅block_return_signal的next block仅仅是将值传递出来,不做额外操作。
结论
所以订阅flattenMap的流程是,订阅源信号,获取源信号的sendNext值value,自己新创建一个信号(创建可能依赖value),自动订阅自己创建的信号(如果信号非空),将自己创建的信号的新value直接吐出来。
- 所以订阅flattenMap的作用是,利用前一个信号的输出,再创建一个信号(可能使用上个输出)做一些操作,再将操作结果输出。
- 所以map的作用是,使用flattenMap,利用前一个信号的输出,再创建一个RACReturnSignal,RACReturnSignal的value就是原信号输出value的转换,再将这个转换值输出。
flattenMap的使用方法
在臧成威的博客中提到接口串联可以使用flattenMap来实现,根据上面的分析和结论可以知道,下一个信号需要等待上一个信号执行完成,传递出value后才能继续。
// 接口串联
@weakify(self)
RACSignal *finalSignal = [[self fetchData4]
flattenMap:^RACSignal *(NSString *data4Result) {
@strongify(self)
return [self fetchData5:data4Result];
}];