如何链接传递结果的 SignalProducers
How to chain SignalProducers passing along the results
给定函数 multiply()
和 convert()
(概念的最小示例,我实际上计划在每个函数中查询远程服务器),什么是更短的实现方式multiplyAndConvert()
?
// call two async functions passing the result the from the first
// as the argument to the second
multiplyAndConvert(3).startWithResult { val in
print("\(val.value!)")
}
func convert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
observer.send(value: String(val))
observer.sendCompleted()
}
}
func multiply(_ val: Int) -> SignalProducer<Int, NSError> {
return SignalProducer<Int,NSError> { observer, _ in
observer.send(value: val * 2)
observer.sendCompleted()
}
}
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
multiply(val).startWithResult { res2 in
switch res2 {
case .success(let val2):
convert(val2).startWithResult { res3 in
switch res3 {
case .success(let val3):
observer.send(value:val3)
observer.sendCompleted()
case .failure(let err):
observer.send(error:err)
}
}
case .failure(let err):
observer.send(error: err)
}
observer.sendCompleted()
}
}
}
我知道必须有一种更优雅的方法来做到这一点,但我不知道它是什么。我玩过 map、flatMap、flatten 和大多数其他函数,但找不到更好的解决方案。
使用平面地图:
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return multiply(val).flatMap(.concat) { multipliedVal in
return convert(multipliedVal)
}
}
你也可以将 convert
作为第二个参数直接传递给 flatMap 而不是给它一个闭包,因为它已经是正确的类型 (Int -> SignalProducer<String, NSError>
)
multiply(val).flatMap(.concat, transform: convert)
但是如果 convert
函数在您的扩展代码中引用 self
这可能会导致保留循环,在这种情况下您需要传递一个闭包捕获 [weak self]
说明
flatMap
在这里做的是接收乘法信号:
-----.value(multipliedValue)-.completed
并使用提供的闭包将其映射到一个信号中:
.value(convertedMultipliedValue)
/
----x-.completed
然后 "flattens" 这个信号中的信号(使用 .Concat 展平策略,它通过连接所有子信号来展平信号中的信号——但这在这里并不重要,因为我们是仅展平单个子信号)给我们:
----.value(convertedMultipliedValue)-.completed
给定函数 multiply()
和 convert()
(概念的最小示例,我实际上计划在每个函数中查询远程服务器),什么是更短的实现方式multiplyAndConvert()
?
// call two async functions passing the result the from the first
// as the argument to the second
multiplyAndConvert(3).startWithResult { val in
print("\(val.value!)")
}
func convert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
observer.send(value: String(val))
observer.sendCompleted()
}
}
func multiply(_ val: Int) -> SignalProducer<Int, NSError> {
return SignalProducer<Int,NSError> { observer, _ in
observer.send(value: val * 2)
observer.sendCompleted()
}
}
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
multiply(val).startWithResult { res2 in
switch res2 {
case .success(let val2):
convert(val2).startWithResult { res3 in
switch res3 {
case .success(let val3):
observer.send(value:val3)
observer.sendCompleted()
case .failure(let err):
observer.send(error:err)
}
}
case .failure(let err):
observer.send(error: err)
}
observer.sendCompleted()
}
}
}
我知道必须有一种更优雅的方法来做到这一点,但我不知道它是什么。我玩过 map、flatMap、flatten 和大多数其他函数,但找不到更好的解决方案。
使用平面地图:
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return multiply(val).flatMap(.concat) { multipliedVal in
return convert(multipliedVal)
}
}
你也可以将 convert
作为第二个参数直接传递给 flatMap 而不是给它一个闭包,因为它已经是正确的类型 (Int -> SignalProducer<String, NSError>
)
multiply(val).flatMap(.concat, transform: convert)
但是如果 convert
函数在您的扩展代码中引用 self
这可能会导致保留循环,在这种情况下您需要传递一个闭包捕获 [weak self]
说明
flatMap
在这里做的是接收乘法信号:
-----.value(multipliedValue)-.completed
并使用提供的闭包将其映射到一个信号中:
.value(convertedMultipliedValue)
/
----x-.completed
然后 "flattens" 这个信号中的信号(使用 .Concat 展平策略,它通过连接所有子信号来展平信号中的信号——但这在这里并不重要,因为我们是仅展平单个子信号)给我们:
----.value(convertedMultipliedValue)-.completed