如何在 ReactiveSwift 中组合 Actions ("run the first enabled action from this list")
How to compose Actions in ReactiveSwift ("run the first enabled action from this list")
我有两个 Action
具有相同的 input/output/error 类型,我想将它们组合成一个 Action
运行两个启用的任何一个(与一个任意的决胜局,如果他们都是。
这是我第一次失败的尝试:
let addOrRemove: Action<MyInput, MyOutput, APIRequestError> = Action(enabledIf: add.isEnabled.or(remove.isEnabled)) { input in
if add.isEnabled.value {
return add.apply(input)
} else {
return remove.apply(input)
}
}
这失败了,因为内部 add.apply(input)
看不到我检查了 add.isEnabled
,所以它在错误类型周围包装了一个额外的 ActionError<>
层。 (这可能是合法的,因为我不确定这种方法的线程安全性如何,或者我们可能知道类型系统不知道的事情。)相应的类型错误是:
cannot convert return expression of type 'SignalProducer<MyOutput, ActionError<APIRequestError>>' to return type 'SignalProducer<MyOutput, APIRequestError>'
我应该怎么做?
Github 用户 @ikesyo provided the following answer on the ReactiveSwift issue I opened to ask the same question:
let producer: SignalProducer<MyOutput, ActionError<APIRequestError>>
if add.isEnabled.value {
producer = add.apply(input)
} else {
producer = remove.apply(input)
}
return producer.flatMapError { error in
switch error {
case .disabled: return .empty
case let .producerFailed(inner): return SignalProducer(error: inner)
}
}
如果他们出现在这里,我会很乐意将已接受的答案更改为他们的答案(归功于它所属的地方)。
警告:如果我正确阅读了这个答案,它并不是无懈可击的。如果 add
在包装 Action
的 apply()
和 start()
之间从启用变为禁用,我们将得到 "success"(没有值,但是 .completed
) 而不是我们应该得到的 .disabled
。这对我的用例来说已经足够了,但是 YMMV。
我有两个 Action
具有相同的 input/output/error 类型,我想将它们组合成一个 Action
运行两个启用的任何一个(与一个任意的决胜局,如果他们都是。
这是我第一次失败的尝试:
let addOrRemove: Action<MyInput, MyOutput, APIRequestError> = Action(enabledIf: add.isEnabled.or(remove.isEnabled)) { input in
if add.isEnabled.value {
return add.apply(input)
} else {
return remove.apply(input)
}
}
这失败了,因为内部 add.apply(input)
看不到我检查了 add.isEnabled
,所以它在错误类型周围包装了一个额外的 ActionError<>
层。 (这可能是合法的,因为我不确定这种方法的线程安全性如何,或者我们可能知道类型系统不知道的事情。)相应的类型错误是:
cannot convert return expression of type 'SignalProducer<MyOutput, ActionError<APIRequestError>>' to return type 'SignalProducer<MyOutput, APIRequestError>'
我应该怎么做?
Github 用户 @ikesyo provided the following answer on the ReactiveSwift issue I opened to ask the same question:
let producer: SignalProducer<MyOutput, ActionError<APIRequestError>>
if add.isEnabled.value {
producer = add.apply(input)
} else {
producer = remove.apply(input)
}
return producer.flatMapError { error in
switch error {
case .disabled: return .empty
case let .producerFailed(inner): return SignalProducer(error: inner)
}
}
如果他们出现在这里,我会很乐意将已接受的答案更改为他们的答案(归功于它所属的地方)。
警告:如果我正确阅读了这个答案,它并不是无懈可击的。如果 add
在包装 Action
的 apply()
和 start()
之间从启用变为禁用,我们将得到 "success"(没有值,但是 .completed
) 而不是我们应该得到的 .disabled
。这对我的用例来说已经足够了,但是 YMMV。