RxSwift - 如何在可观察的更改但仅发出最后一个值时重试?

时间:2017-03-29 14:51:02

标签: swift reactive-programming reactive-cocoa rx-swift

我试图与RxSwift建立聊天服务链。 基本上应该这样做:

  • 检查聊天是否有id,如果是,则转到下一个,如果没有flatMap来创建服务
  • 检查sockect连接是否已启用
  • 发送聊天消息

基本上下面的功能有效,但现在不检查套接字连接状态。 它应该在第二个flatMap之前检查是否连接套接字,如果是,它应该使用messageUpload转到flatMap,否则它应该等到connection返回true。 我有变量告诉我当前的连接状态(Bool)

chatSocketService.isSubscribedToChannel.asObservable()

但我无法弄清楚如何将它们组合在一起。 我尝试了第三个flatMap(在当前的最后一个之前)它没有用。 接下来的问题是用户可以在连接恢复之前尝试发送几条消息,因此每次他执行sendButton时都会执行此方法,因此它应该在连接返回时仅发送最后一条消息。 知道如何用Rx处理它吗?

func sendMessage(withBody body: String) {
    guard !body.isEmpty else { return }

    Observable.just(chatModel.value)
        .filter({ $0.product != nil })
        .flatMap({ [unowned self] chatModel -> Observable<ChatModel> in
            if chatModel.id != nil {
                return Observable.just(chatModel)
            } else {
                return self.createChat(withProductModel: chatModel.product!)
            }
        })
        .flatMap({ [unowned self] chatModel -> Observable<ChatMessageModel> in
            return self.chatService.uploadChatMessage(forChat: chatModel, withBody: body)
                    .trackActivity(self.progressHelper.activityIndicator)
        })
        .subscribe(onNext: { [unowned self] chatMessageModel in
            self.finishedSendingMessage.onNext(())
        })
        .addDisposableTo(disposeBag)
}

1 个答案:

答案 0 :(得分:2)

.flatMap({ [unowned self] chatModel -> Observable<ChatMessageModel> in
    let successfulConnect = chatSocketService.isSubscribedToChannel.asObservable()
       .skipWhile { $0 == false }
       .map { _ -> Void in }
       .take(1)

    return successfulConnect.flatMap { self.chatService.uploadChatMessage(forChat: chatModel, withBody: body) }
        .trackActivity(self.progressHelper.activityIndicator)
})

上述代码应具有管理连接问题中描述的行为。 successfulConnect是一个可观察的,当连接状态为真时,它将发出一个值并完成。

skipWhile将忽略false个值,map将我们的观察点从Observable<Bool>转换为Observable<Void>take(1)确保观察点在完成之后完成第一个价值。 flatMap会在uploadChatMessage发送值时执行sucessfulConnect

您描述的第二个行为意味着如果用户在上一个上传之前发送了另一条消息,则取消之前的上传。这可以通过在输入sendMessage

时处理订阅来处理
var disposable: Disposable?

func sendMessage(withBody body: String) {
   disposable?.dispose()
   disposable = Observable.just(chatModel.value)
      // ...
      .subscribe(onNext: { /* ... */ })
}