这里采用与问题 39 类似的示例:http://reactivex.io/learnrx/
我正在尝试将方法调用 search(query: String)
转换为这些调用的序列。
我实现这一目标的方法是创建一个 Variable
,每次我都会使用 query
值更新该变量
调用 search(query: String)
方法。
然后我的 init()
中有这个:
_ = queryVariable.asObservable().flatMap({ query -> Observable<[JSON]> in
return self.facebookSearch(query).takeUntil(self.queryVariable.asObservable())
}).subscribeNext({ result in
if let name = result[0]["name"].string {
print(name)
} else {
print("problem")
}
})
如果我输入 "ABC"
,我的 search(query: String)
方法将被调用 3 次,"A"
, “AB”
,“ABC”
。
它将通过 queryVariable.asObservable()
映射到 seq(["A", "AB", "ABC"])
。
然后我将其映射到 Facebook 搜索(在 Facebook 上按姓名搜索人员)。
然后使用 subscribeNext
打印名称。
如果我不使用 takeUntil
,它会按我的预期工作,我会得到 3 组结果,每个查询对应一组结果("A"
, “AB”
,“ABC”
)。
但是,如果我输入速度很快(在 Facebook 有时间响应请求之前),我只需要一个结果,即查询“ABC”
。这就是我添加 takeUntil
的原因。有了它,我希望在下一个查询到来时忽略 facebookSearch(query: String) 调用,但当前查询将被取消,因此这个 takeUntil
我最终没有打印任何内容。
这是一个已知问题还是我做错了什么?
最佳答案
我使用了您的代码并找到了解决您问题的两种解决方案:
<强>1。使用flatMapLatest
您可以只使用 flatMapLatest
而不是 flatMap
和 takeUntil
。 flatMapLatest
仅返回最新搜索请求的结果,并取消所有尚未返回的旧请求:
_ = queryVariable.asObservable()
.flatMapLatest { query -> Observable<String> in
return self.facebookSearch(query)
}
.subscribeNext {
print($0)
}
<强>2。使用分享
为了使您的方法发挥作用,当您将 queryVariable
Observable 也用于 takeUntil
时,您必须共享它的事件:
let queryObservable = queryVariable.asObservable().share()
_ = queryObservable
.flatMap { query -> Observable<String> in
return self.facebookSearch(query).takeUntil(queryObservable)
}
.subscribeNext {
print($0)
}
如果您不共享事件,takeUntil
中的 searchQuery.asObservable()
将创建自己的(重复)序列。然后,当在 searchQuery
变量上设置新值时,它会立即触发 takeUntil() 序列中的 Next 事件,并取消 facebookSearch 结果。
当您使用share()
时,takeUntil
中的序列正在观察与其他序列相同的事件,在这种情况下,takeUntil
序列在 facebookSearch 返回响应后处理 Next 事件。
恕我直言,第一种方法(flatMapLatest)是处理这种情况的首选方法。
关于ios - RXSwift - takeUntil 在下一个事件之前取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36534964/