RXSwift - takeUntil 在下一个事件之前取消

RXSwift - takeUntil canceling before next event

这里是问题 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"。 这将映射到 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 仅 returns 最新搜索请求的结果并取消所有尚未返回的旧请求:

_ = queryVariable.asObservable()
    .flatMapLatest { query -> Observable<String> in
        return self.facebookSearch(query)
    }
    .subscribeNext {
        print([=10=])
    }

2。使用 share

为了让你的方法奏效,你必须分享你的 queryVariable Observable 的事件,同时你也将它用于 takeUntil:

let queryObservable = queryVariable.asObservable().share()

_ = queryObservable
    .flatMap { query -> Observable<String> in
        return self.facebookSearch(query).takeUntil(queryObservable)
    }
    .subscribeNext {
        print([=11=])
    }

如果您不共享事件,takeUntil 中的 searchQuery.asObservable() 会创建自己的(重复)序列。然后,当在 searchQuery 变量上设置新值时,它会立即触发 takeUntil() 序列中的 Next 事件并取消 facebookSearch 结果。

当您使用 share() 时,takeUntil 中的序列正在观察与另一个序列相同的事件,在这种情况下,takeUntil 序列会在 facebookSearch 返回后处理 Next 事件回应。

恕我直言,第一种方式 (flatMapLatest) 是处理这种情况的首选方式。