gpt4 book ai didi

ios - 如何有条件地缓冲 RACSignal 值?

转载 作者:技术小花猫 更新时间:2023-10-29 11:03:07 26 4
gpt4 key购买 nike

我正在编写一些通过 websockets 与远程 API 交互的代码。我的数据层负责建立和监控 websocket 连接。它还包含应用程序可以用来对要发送的 websocket 消息进行排队的方法。应用程序代码不应该负责检查 websocket 连接的状态,也就是即发即弃。

理想情况下,我希望数据层的功能如下:

  • 当数据层没有连接到 websocket 端点时(self.isConnected == NO),消息在内部缓冲。
  • 当连接可用时(self.isConnected == YES),缓冲消息会立即发送,任何后续消息也会立即发送。

这是我能够想出的:

#import "RACSignal+Buffering.h"

@implementation RACSignal (Buffering)

- (RACSignal*)bufferWithSignal:(RACSignal*)shouldBuffer
{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];

NSMutableArray* bufferedValues = [[NSMutableArray alloc] init];
__block BOOL buffering = NO;

void (^bufferHandler)() = ^{
if (!buffering)
{
for (id val in bufferedValues)
{
[subscriber sendNext:val];
}

[bufferedValues removeAllObjects];
}
};

RACDisposable* bufferDisposable = [shouldBuffer subscribeNext:^(NSNumber* shouldBuffer) {

buffering = shouldBuffer.boolValue;
bufferHandler();

}];

if (bufferDisposable)
{
[disposable addDisposable:bufferDisposable];
}

RACDisposable* valueDisposable = [self subscribeNext:^(id x) {

[bufferedValues addObject:x];
bufferHandler();

} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
[subscriber sendCompleted];
}];

if (valueDisposable)
{
[disposable addDisposable:valueDisposable];
}

return disposable;
}];
}

@end

最后,这是关于如何使用它的伪代码:

@interface APIManager ()

@property (nonatomic) RACSubject* requests;

@end

@implementation WebsocketDataLayer

- (id)init
{
self = [super init];

if (self) {

RACSignal* connectedSignal = RACObserve(self, connected);

self.requests = [[RACSubject alloc] init];

RACSignal* bufferedApiRequests = [self.requests bufferWithSignal:connectedSignal];

[self rac_liftSelector:@selector(sendRequest:) withSignalsFromArray:@[bufferedApiRequests]];
}
return self;
}

- (void)enqueueRequest:(NSString*)request
{
[self.requests sendNext:request];
}

- (void)sendRequest:(NSString*)request
{
DebugLog(@"Making websocket request: %@", request);
}

@end

我的问题是:这是缓冲值的正确方法吗?是否有更惯用的 RAC 方式来处理这个问题?

最佳答案

缓冲可以被认为是应用于个别请求的东西,这导致使用-flattenMap:RACObserve 的自然实现:

@weakify(self);
RACSignal *bufferedRequests = [self.requests flattenMap:^(NSString *request) {
@strongify(self);

// Waits for self.connected to be YES, or checks that it already is,
// then forwards the request.
return [[[[RACObserve(self, connected)
ignore:@NO]
take:1]
// Replace the property value with our request.
mapReplace:request];
}];

如果顺序很重要,您可以将 -flattenMap: 替换为 -map: 加上 -concat。这些实现避免了对任何自定义运算符的需要,并且无需手动订阅(这是出了名的困惑)。

关于ios - 如何有条件地缓冲 RACSignal 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19525160/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com