Search code examples
iosswiftrx-swift

How do I proceed to the next andThen if the value in the current andThen is nil?


I have chained multiple calls to the same Completable like this:

self.viewModel.setParameter(parameter: lockReleaseTime)
                    .andThen(Completable.deferred { self.viewModel.setParameter(parameter: lockRelease) })
                    .andThen(Completable.deferred { self.viewModel.setParameter(parameter: lockVoltage) })
                    .andThen(Completable.deferred { self.viewModel.setParameter(parameter: lockPowered) })
                    .andThen(Completable.deferred { self.viewModel.setParameter(parameter: lockPowered) })
                    .andThen(Completable.deferred { self.viewModel.setParameter(parameter: lockInstall) })
                    .andThen(Completable.deferred { self.viewModel.setParameter(parameter: lockKick) })
                    .subscribe(onCompleted: {
                        print("-- Done setting parameter")
}).disposed(by: self.disposeBag)

The problem here is that the arguments can be nil (lockRelease, lockVoltage, etc); and if they are, I just want to skip the current andThen and proceed to the next andThen sort of like this:

.andThen(Completable.deferred {
    guard let lockRelease = lockRelease else {
        Completable.skipToNextAndThen
     }
                        
    return self.viewModel.setParameter(parameter: lockRelease) })

Is it possible to do something like this?


Solution

  • Your skipToNextAndThen is called .empty(). Also, there's no need for the deferreds in this situation. As in:

    func example() {
        setOptionalParameter(parameter: lockReleaseTime)
            .andThen(setOptionalParameter(parameter: lockRelease))
            .andThen(setOptionalParameter(parameter: lockVoltage))
            .andThen(setOptionalParameter(parameter: lockPowered))
            .andThen(setOptionalParameter(parameter: lockInstall))
            .andThen(setOptionalParameter(parameter: lockKick))
            .subscribe(onCompleted: {
                print("-- Done setting parameter")
            })
            .disposed(by: disposeBag)
    }
    
    func setOptionalParameter(parameter: Param?) -> Completable {
        guard let parameter = parameter else { return .empty() }
        return viewModel.setParameter(parameter: parameter)
    }
    

    Also, instead of all the andThens, you can use concat:

    Completable.concat(
        setOptionalParameter(parameter: lockReleaseTime),
        setOptionalParameter(parameter: lockRelease),
        setOptionalParameter(parameter: lockVoltage),
        setOptionalParameter(parameter: lockPowered),
        setOptionalParameter(parameter: lockInstall),
        setOptionalParameter(parameter: lockKick)
    )
    .subscribe(onCompleted: {
        print("-- Done setting parameter")
    })
    .disposed(by: disposeBag)
    

    Also, I expect they don't really have to be done one at a time, in order. If not, you can use zip:

    Completable.zip(
        setOptionalParameter(parameter: lockReleaseTime),
        setOptionalParameter(parameter: lockRelease),
        setOptionalParameter(parameter: lockVoltage),
        setOptionalParameter(parameter: lockPowered),
        setOptionalParameter(parameter: lockInstall),
        setOptionalParameter(parameter: lockKick)
    )
    .subscribe(onCompleted: {
        print("-- Done setting parameter")
    })
    .disposed(by: disposeBag)