RAC 4 Swift失败的方法

时间:2015-11-11 07:23:08

标签: swift reactive-cocoa

ReactiveCocoa 4在SignalProducerthen上有一个等待生产者完成的方法,并将其替换为另一个生产者,如下所示:

someProducer.then(replacementProducer)

然而我想要的是一个等待原始生成器出错然后用第二个生成器替换它的方法(在完成事件上什么都不做)。

then实现为(注意不转发下一个事件):

public func then<U>(replacement: SignalProducer<U, Error>) -> SignalProducer<U, Error> {
    let relay = SignalProducer<U, Error> { observer, observerDisposable in
        self.startWithSignal { signal, signalDisposable in
            observerDisposable.addDisposable(signalDisposable)

            signal.observe { event in
                switch event {
                case let .Failed(error):
                    observer.sendFailed(error)
                case .Completed:
                    observer.sendCompleted()
                case .Interrupted:
                    observer.sendInterrupted()
                case .Next:
                    break
                }
            }
        }
    }
    return relay.concat(replacement)
}

我想要的看起来很相似,除非失败,而不是发送错误,它会发送一个完整的信号。更具体地说,switch语句将改为:

signal.observe { event in
    switch event {
        case .Failed:
            observer.sendCompleted()
        case .Completed, .Next: break
        case .Interrupted:
            observer.sendInterrupted()
        }
    }
}

我的问题如下:

1)这有效吗?它按照我的预期工作,替换信号仅在第一个信号出错时才开始。 2)有没有更好的方法来做错误信息不会丢失?

我将使用它的一个示例是两步验证过程:

self.verifyToken(token).failed(self.revalidateSession())

如果令牌验证成功,一切都很好,无需重新验证。如果失败,则需要进行重新验证。

编辑:

我更改了信号观察块,这样如果第一个信号没有错误就完成了,它会用startWithComplete启动替换信号,这样完成事件就会在链中转发,而不会触发信号的任何动作。

这样可以很容易地做到这一点:

self.verify(token).failed(self.refreshSession(token)).then(self.fetchUserForToken(token))

其中then被链接,只有在verifyrefreshSession成功时才会执行。

signal.observe { event in
    switch event {
        case .Failed:
            observer.sendCompleted()
        case .Completed:
            replacement.startWithCompleted {}
        case .Next: break
        case .Interrupted:
            observer.sendInterrupted()
        }
    }
}

1 个答案:

答案 0 :(得分:1)

1)这有效吗?

没有。如果验证信号生成器发送正常值并完成,则替换信号生成器确实启动(通过startWithCompleted调用)但不会产生任何结果(因为您没有观察到startWithCompleted闭包中的任何内容,并且内部replay信号生成器永远不会终止。

2)有更好的方法吗?

您可以使用flatMapError运算符,这样您也可以获取错误信息。

self.verify(token)
    .map { _ in () }
    .flatMapError { error in
        return self.refreshSession(token).map { _ in () }
    }

注意,如果map { _ in () }生成器和veriy生成器生成相同类型的值,则可以省略两个refreshSession