以下是与问题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而不是flatMaptakeUntilflatMapLatest仅返回最新搜索请求的结果,并取消所有尚未返回的旧请求:

_ = 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/

10-14 23:16