以下是与问题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)
方法将被"A"
,"AB"
和"ABC"
调用3次。那将被映射到
seq(["A", "AB", "ABC"])
与queryVariable.asObservable()
。然后,我将其映射到Facebook搜索(通过在Facebook上按其姓名搜索人员)。
并使用
subscribeNext
打印名称。如果我不使用
takeUntil
,它会按我期望的那样工作,那么我将获得3组结果,每个查询一组("A"
,"AB"
,"ABC"
)。但是,如果我快速键入(在Facebook有时间响应请求之前),则查询
"ABC"
只需要一个结果。这就是为什么我添加了takeUntil
的原因。有了它,我希望下一个facebookSearch(query: String)
进来时会忽略query
调用,但是对于当前查询它会被取消,因此使用此takeUntil
我最终什么都不打印。这是一个已知问题还是我做错了什么?
最佳答案
我使用了您的代码,找到了两种解决问题的方法:
1.使用flatMapLatest
您可以只使用flatMapLatest
而不是flatMap
和takeUntil
。 flatMapLatest
仅返回最新搜索请求的结果,并取消所有尚未返回的旧请求:
_ = queryVariable.asObservable()
.flatMapLatest { query -> Observable<String> in
return self.facebookSearch(query)
}
.subscribeNext {
print($0)
}
2.使用
share
为了使您的方法可行,您还必须将
queryVariable
Observable事件也共享给takeUntil
:let queryObservable = queryVariable.asObservable().share()
_ = queryObservable
.flatMap { query -> Observable<String> in
return self.facebookSearch(query).takeUntil(queryObservable)
}
.subscribeNext {
print($0)
}
如果您不共享事件,则
searchQuery.asObservable()
中的takeUntil
将创建自己的(重复)序列。然后,当在searchQuery
变量上设置了新值时,它将立即触发takeUntil()序列中的Next事件,并取消facebookSearch结果。当您使用
share()
时,takeUntil
中的序列会观察到与其他序列相同的事件,在这种情况下,takeUntil
序列会在facebookSearch返回响应后处理Next事件。恕我直言,第一种方法(flatMapLatest)是处理这种情况的首选方法。
关于ios - RXSwift-takeUntil在下一个事件之前取消,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36534964/