是否有一种 Combine-y 方法来停止触发多个请求?

Is there a Combine-y way to stop multiple requests being triggered?

我目前有这样的代码...

var isFetching = false

func fetch() {
  guard !isFetching else { return }
  fetching = true

  apiPublisher
    .receive(on: .main)
    .handleEvents(receiveCompletion: { [weak self] _ in
      self?.fetching = false
    })
    .assign(to: \.foo, on: self)
    .store(in: &cancellables)
}

但是我对我停止像这样发生的多个请求的方式不满意。它有效,但感觉笨重。

我觉得应该有一种更“结合”的方式来做到这一点。

有没有更多的elegant/Combine-y方法来做到这一点?

这里的问题是您在函数 (fetch()) 中拥有整个 Publisher 订阅链,几乎任何其他代码几乎可以在任何时间从任何线程调用该函数 (fetch())。为了在“更多的 Combine-y”中执行此操作,您需要对其进行限制。那么问题来了,这个fetch()函数是怎么调用的呢?如果您将所有这些呼叫站点包装在 Publisher 中,然后设置 trigger.flatMap { apiPublisher } 并设置 flatMap 以在等待当前网络请求完成时忽略事件。

像这样:

    trigger
        .flatMap(maxPublishers: .max(1)) {
            apiPublisher
        }
        .receive(on: .main)
        .assign(to: \.foo, on: self)
        .store(in: &cancellables)

这里要注意的重要一点是你只执行这段代码一次(如果这是一个视图控制器,可能在 viewDidLoad 中执行。然后当你想发出请求时,你通过 trigger 发布者。flatMap 将确保一次只有一个 apiPublisher 订阅。