【问题标题】:How can I split a signal and merge it in again later?如何拆分信号并稍后再次合并?
【发布时间】:2015-03-07 15:30:27
【问题描述】:

我不太确定如何正确地做到这一点,而且我可能错过了一些关于 FRP 的概念,因为我没有长时间使用 ReactiveCocoa。

我的情况是这样的 - 我有信号:

  • 从本地存储加载对象;
  • 从远程存储加载对象;
  • 将远程对象保存到本地存储;
  • 将本地存储中的对象转换(映射)为不同的格式

我想要一个可以订阅的信号,它将:

  • 通过 localId 从本地存储加载对象;
  • 在此处将信号拆分为:
    • 向信号的订阅者发送一个初始对象:
      • 将对象转换为不同的格式;
      • 将此格式发送给最终订阅者;
    • 从远程存储更新本地对象并发送更新版本;
      • 使用刚刚加载的本地对象的 remoteId 从远程存储加载对象;
      • 将该远程对象保存到本地存储;
      • 从本地存储中从原始 localId 重新加载对象;
      • 将对象转换为不同的格式;
      • 将此格式发送给最终订阅者;
      • 完成信号。

这一切背后的想法是,我的主要加载对象信号应该返回对象的初始版本(本地存储),同时从远程存储更新该对象并最终发送更新的版本。所以最终订阅者应该在完成之前收到两次对象。

远程加载信号依赖于本地加载信号,因为我们必须加载本地对象才能获得对象的remoteId。因此,我想避免在启动信号时两次加载本地对象(一次用于发送给原始订阅者,一次用于获取 remoteId 以加载远程对象)。

我想出的最初解决方案是使本地加载信号成为多播 (autoconnected) 信号,然后将该信号(与转换链接到它)与相同的信号(与远程加载,保存,加载和转换链接到它)。但是,这永远不会进行远程加载,我只能认为这是由于本地加载信号发送completed。

有什么方法可以做我想做的事吗?我的逻辑完全错了吗? 提前感谢您的任何建议。

【问题讨论】:

    标签: reactive-cocoa frp


    【解决方案1】:

    一种可能性是使用主题。如果您不熟悉,可以订阅主题,就像普通的信号一样,但您可以明确告诉它发送值(或错误,或完成的消息)。您还可以为 Subject 订阅 Signal,Subject 会将 Signal 的消息传播给它自己的订阅者。

    您可能希望以更漂亮的方式封装它,但我认为类似以下的内容会满足您的需求:

    let subject = RACSubject()
    
    subject.map {
        let localObject = $0 as! LocalObjectType
        return transformLocalFormToFinalForm(localObject)
    }
    .subscribeNext { 
        let finalObject = $0 as! FinalObjectType
        // Process your final object here
    }
    
    
    let localObjectId = ... // Assuming the ID exists
    
    getLocalObject(localObjectId).doNext { 
        subject.sendNext($0) 
    }
    .flattenMap {
        let localObject = $0 as! LocalObjectType
        return getRemoteObject(localObject.remoteId)
    }
    .flattenMap {
        let remoteObject = $0 as! RemoteObjectType
        return saveRemoteObjectToLocalStore(remoteObject)
    }
    .flattenMap {
        return getLocalObject(localObjectId)
    }
    .subscribeNext({
        subject.sendNext($0)
        subject.sendCompleted()
    }, error {
        subject.sendError($0)
    })
    

    此设置应执行以下操作:

    1. 从 ID 获取本地对象
    2. 将本地对象发送给主体(这将被转换并发送给最终订阅者)
    3. 使用本地对象的远程ID获取远程对象
    4. 将远程对象保存到本地存储
    5. 从原始 ID 获取(现已更新的)本地对象
    6. 向主题发送本地对象和完整的消息(或错误,如果在链中的任何地方发生错误)

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2012-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多