TCA における Swift Concurrency 時代の debounce

2023/06/28に公開

Combine 時代に利用していた debounce は deprecated になっています。

https://github.com/pointfreeco/swift-composable-architecture/blob/42b01f284e9dcd06131bda03c1ac6dec8230aae9/Sources/ComposableArchitecture/Effects/Publisher/Debouncing.swift#L47-L68

Swift Concurrency を利用している場合は、以下の withTaskCancellation が用意されているため、それで debounce を実現することができます。

https://github.com/pointfreeco/swift-composable-architecture/blob/b9defab12c95afe46b325669ed101a974472ac6d/Sources/ComposableArchitecture/Effects/Cancellation.swift#L152-L179

withTaskCancellation の上の方にドキュメントコメントで使用方法が記載されていますが、Clock と組み合わせて以下のようにすれば、キャンセルの挙動によって debounce が実現できます。

@Dependency(\.continuousClock) var clock
enum CancelID { case response }

// ...

return .run { send in
  await withTaskCancellation(id: CancelID.response, cancelInFlight: true) {
    try await self.clock.sleep(for: .seconds(0.3))
    await .send(
      .debouncedResponse(TaskResult { try await environment.request() })
    )
  }
}

Discussion