我的任务是为应用程序添加一些检测逻辑,以跟踪各种API调用的延迟.我正在努力想出一种干净的,无副作用的方法来为返回RACSignal(延迟执行API调用)的方法添加时序检测.
注意事项
>使用ReactiveCocoa @ 1.9.5(目前无法升级)
>使用Parse-RACExtensions @ 0.0.2
>我更喜欢在viewmodel层设置时序,而不是修改Parse-RACExtensions.这是因为VM有我想记录的额外信息,比如查询参数,而且我不需要每个API调用.
>仅在收到完成的事件后记录时间
>本着无痛仪器的精神,呼叫者的负担应该尽可能小
试图解决方案
我唯一能想到的就是创建一个处理定时器逻辑的具体RACSubscriber子类.除了令人讨厌的子类,这显然不是理想的,因为它需要一个显式的subscribe:,这反过来需要重放源信号.此外,调用者还有一个负担,因为他们必须至少重构以获得信号的临时句柄.
@interface SignalTimer : RACSubscriber @property (nonatomic) NSDate *startDate; @end @implementation SignalTimer - (void)didSubscribeWithDisposable:(RACDisposable *)disposable { [super didSubscribeWithDisposable:disposable]; self.startDate = [NSDate date]; } - (void)sendCompleted { NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:self.startDate]; NSLog(@"Time elapsed: %f",duration); [super sendCompleted]; } @end
用法如下所示:
- (RACSignal*)saveFoo:(Foo*)fooParSEObj { RACSignal *save = [[fooParSEObj rac_save] replay]; // Don't forget replay! [save subscribe:[[SignalTimer alloc] initWithName@"Saving the user's foo object"]]; return save; }
显然,我对这个实现不满意.
最后的想法
理想情况下,我喜欢像这样的链式方法,但是我不知道如何实现它/如果可以在类别方法中处理冷信号而没有令人讨厌的副作用(比如在接收器上调用重放) ).
[[[fooParSEObj rac_save] logTimingsWithName:@"Saving the user's foo object"] subscribeNext:...];
思考?
解决方法
所以我认为我这样做比他们需要的更难.以下类别解决方案似乎更惯用,但我喜欢任何反馈.
@interface RACSignal (Timing) - (instancetype)logTimingWithName:(NSString*)name; @end @implementation RACSignal (Timing) - (instancetype)logTimingWithName:(NSString*)name { return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { NSDate* startDate = [NSDate date]; return [self subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startDate]; NSLog(@"%@: %f sec",name,duration); [subscriber sendCompleted]; }]; }]; } @end