如何在RxSwift中翻译if-else?

时间:2015-09-02 16:56:20

标签: swift reactive-programming rx-swift

我正在尝试学习图书馆RxSwift

我有一些像这样的代码:

if data.checkAllIsOk()
{ 
    [do things]
}
else
{ 
    [show alert]
}

现在我需要在检查之前更新服务器中的数据,因此我建模了一个返回Observable的getData()。

我目前的做法是:

getData()  
    >- flatMap{ (data:Data) -> Observable<Bool> in
        _=0 // workaround for type inference bugs
        return just(data.checkAllIsOk())
    }
    >- subscribeNext{ (ok) -> Void in
        if ok
        {
            [do the things]
        }
        else
        {
            [show the alert]
        }
    } 
    >- disposeBag.addDisposable()

它有效(或者它应该,我仍然在写它),但它感觉不对..是否有更多的&#34;反应性&#34;这样做的方法? 什么是最合适的运营商?

可能为“false”返回错误并使用catch块?

更新

按照ssrobbi建议的方法,我在2个不同的subscribeNext中拆分了2个分支,并使用过滤器来选择正或负分支。这是产生的代码:

let checkData=getData()  
        >- flatMap{ (data:Data) -> Observable<Bool> in
            _=0 
            return just(data.checkAllIsOk())
        }
        >- shareReplay(1)
}
[...]
checkData
    >- filter{ (ok) -> Bool in
        ok == true
    }
    >- subscribeNext{ (_) -> Void in
        [do the things]
    }
    >- disposeBag.addDisposable()

checkData
    >- filter{ (ok) -> Bool in
        ok == false
    }
    >- subscribeNext{ (_) -> Void in
        [show the alert]
    } 
    >- disposeBag.addDisposable()

这种方法的优点是我可以只重用代码的其他部分中的两个分支中的一个,而不重写订阅体(更少的重复总是好的!)

更新

在RxSwift松弛中进行了一些讨论后,我添加了shareReplay(1),因此getData()不会重复。

4 个答案:

答案 0 :(得分:5)

老实说我还在学习,现在我没有RxSwift在我面前(如果我正在喷射BS,有人会纠正我),但也许我可以带领你进入正确的方向。

你的解决方案确实有效,但正如你所说,它不是很“反应”。我认为问题在于您的数据流设置方式必须对是否显示警报或执行操作做出必要的决定。应该发生的是,不是getData返回一个可观察的,getData应该得到它需要的任何数据(无论是来自网络,核心数据等),然后它应该更新一个可观察的属性

对于做事: 现在,您将观察该属性,将其映射以检查它是否正常,并像您一样订阅它,检查它是否为真,以及它是否正在执行。 (并添加一次性)

提醒: 你会做同样的事情,再次观察同一个属性,但检查相反的情况并做一些事情。

我认为对它没有超级反应的是你正在等待来自getData()函数的响应,这会创建一个你现在有状态的场景,是否显示警报,或者做多余的事情工作。它们不是来自其他一些财产的价值流。显示警报和执行操作仅相互关联,因为您必须设置代码。

编辑:而不是使用if语句检查是否为真,也许您可​​以在订阅之前通过过滤器进行检查。

答案 1 :(得分:3)

getData()应返回Observable<Data>,并且所包含的数据已经正常。换句话说,如果正确实现getData(),那么对从observable推出的数据调用data.checkAllIsOk()应始终返回true。

所以你应该在getData()之外的东西(在Rx v2中使用Swift v2):

getData().subscribe { event in 
switch event {
case .Next(let data):
    [do things with data]
case .Error(let error):
    [show the alert]
}

答案 2 :(得分:2)

我不知道RXSwift,但我确实知道函数式编程(RXSwift也是有用的)。 if else语句已经在其最低形式,并且您不需要执行功能分支,这可能会起作用但会降低其可读性。

如果你想要更具功能性,你可以将你的if else改为condition ? a : b(Haskell's if else就是这样)。但这也使它的可读性降低,我会坚持你所得到的;)

答案 3 :(得分:1)

您更新方法的问题是checkDataObservable<Bool>,因此您无法真正“使用它”。

我认为你想要的是这个(为清晰起见而分解):

func isDataOk(_ data: Data) -> Bool { /* ... */ }

let data = getData().shareReplay(1)

let goodData = data.filter(isDataOk)
let badData = data.filter{ isDataOk($0) == false }

goodData
  .subscribe( /* do stuff */ )
  .addDisposableTo(disposeBag)

badData
  .subscribe( /* show alert */ )
  .addDisposableTo(disposeBag)

但我同意Daniel的观点,认为这是一个使用可观察错误的好机会。像这样:

func passOrThrow(_ data: Data) throws -> Data { /* throw an error here if data is bad */ }

getData()
  .map(passOrThrow)
  .subscribe(onNext: { data in
    // do the things
  }, onError: { error in
    // show the alert
  }).addDisposableTo(disposeBag)