所以我有一些RxSwift代码,我想要执行一系列异步操作,所有操作都是使用observable组成的。 flatMap
是实现此目的的方法,并且它运行良好,但它似乎无法将变量传递到我能够找到的链中。一些伪代码最好地说明了这一点
假设有3个功能
class Connection {
static func establish(address:String) -> Observable<Connection>
func sendData(data:String) -> Observable<Int> // num bytes written or something
func close() -> Observable<Void>
}
我想把它们称为链,这样我们就可以连接,发送,然后关闭。像这样的东西
Connection.establish(host)
.flatMap{ connection in connection.sendData("foo") }
.flatMap{ numBytes in ????.close() }
.subscribeNext{ /* all done */ }
问题是flatMap
没有在链中传递它的输入参数,因此传递给subscribeNext
的闭包不能访问connection
对象,并且这样就不能打电话了。
我可以像下面这样做一些可怕的黑客,但我真的不愿意!
var connection:Connection?
Connection.establish(host)
.flatMap{ c in
connection = c
return c.sendData("foo")
}
.flatMap{ numBytes in connection!.close() }
.subscribeNext{ /* all done */ }
在Rx的C#版本中,这是通过使用SelectMany
的重载来解决的,该重载采用第二个闭包,它结合了2个值(通常是一个元组)然后 东西沿着链条传播。我把它写成RxSwfit的扩展,它的工作原理如下:
Connection.establish(host)
.flatMap(
{ connection in connection.sendData("foo") },
combine: { ($0, $1) }) // tupleify
.flatMap{ (connection, numbytes) in connection.close() }
.subscribeNext{ /* all done */ }
这一切都很好,但我的主要问题是 - 有没有更好的方法来实现这个内置于RxSwift目前的立场?
此外,编写此扩展方法并不简单也不容易。我基本上是通过复制/粘贴MiniRxSwift中的那个并重新修改它来从头开始重新实现FlatMap。如果我们必须编写此扩展,是否有更好的方法使用RxSwift构造实现它?
答案 0 :(得分:1)
您可以在establish
功能中执行此操作。它可能看起来像这样:
static func establish(address:String) -> Observable<Connection> {
return Observable.create { observer in
//create connection
observer.onNext(connection)
observer.onCompleted()
return AnonymousDisposable { connection.close() }
}
}
当您observer
处置时,它也会关闭您的连接
我认为这是最好的选择之一。
但是,我们可以使用combineLatest
或flatMap
或其他函数通过链传递连接。但这将是乏味的:)
回复Orion Edwards
不确定这会起作用;在我的例子中,一次性用品从不 实际上,我们希望尽快关闭连接 操作完成
嗯,我很确定这就是RxSwift的人会做的事情。
如果您得到了结果,无论是completed
还是error
,您都会处置观察者。如果你想再次这样做,那么你re-subscribe
。
您可以使用其中一个功能进行处理:
take
系列:take(1)
,takeUntil
... dispose()
。 (劝阻)debug()
查看观察员的处置时间答案 1 :(得分:1)
“使用RxSwift构造”有两种方法可以完成所需的工作。
Connection.establish(host)
.flatMap { Observable.combineLatest(Observable.just($0), $0.sendData("foo")) }
.flatMap { connection, _ in connection.close() }
.subscribe(onNext: { /* all done */ })
或者如果您不介意插入地图,则可以:
Connection.establish(host)
.flatMap { connection in
connection.sendData("foo").map { (connection, $0) }
}
.flatMap { connection, _ in connection.close() }
.subscribe(onNext: { /* all done */ })
请注意,combineLatest
和map
都从一开始就在库中。