@@ -33,14 +33,15 @@ public actor Debouncer<Parameter> {
3333 private let makeCall : ( Parameter ) async -> Void
3434
3535 /// In the time between the call to `scheduleCall` and the call actually being committed (ie. in the time that the
36- /// call can be debounced), the task that would commit the call (unless cancelled) and the parameter with which this
37- /// call should be made.
38- private var inProgressData : ( Parameter , Task < Void , Never > ) ?
36+ /// call can be debounced), the task that would commit the call (unless cancelled), the parameter with which this
37+ /// call should be made and the time at which the call should be made. Keeping track of the time ensures that we don't
38+ /// indefinitely debounce if a new `scheduleCall` is made every 0.4s but we debounce for 0.5s.
39+ private var inProgressData : ( Parameter , ContinuousClock . Instant , Task < Void , Never > ) ?
3940
4041 public init (
4142 debounceDuration: Duration ,
4243 combineResults: @escaping ( Parameter , Parameter ) -> Parameter ,
43- _ makeCall: @escaping ( Parameter ) async -> Void
44+ _ makeCall: @Sendable @ escaping ( Parameter) async -> Void
4445 ) {
4546 self . debounceDuration = debounceDuration
4647 self . combineParameters = combineResults
@@ -52,26 +53,28 @@ public actor Debouncer<Parameter> {
5253 /// `debounceDuration` after the second `scheduleCall` call.
5354 public func scheduleCall( _ parameter: Parameter ) {
5455 var parameter = parameter
55- if let ( inProgressParameter, inProgressTask) = inProgressData {
56+ var targetDate = ContinuousClock . now + debounceDuration
57+ if let ( inProgressParameter, inProgressTargetDate, inProgressTask) = inProgressData {
5658 inProgressTask. cancel ( )
5759 parameter = combineParameters ( inProgressParameter, parameter)
60+ targetDate = inProgressTargetDate
5861 }
5962 let task = Task {
6063 do {
61- try await Task . sleep ( for : debounceDuration )
64+ try await Task . sleep ( until : targetDate )
6265 try Task . checkCancellation ( )
6366 } catch {
6467 return
6568 }
6669 inProgressData = nil
6770 await makeCall ( parameter)
6871 }
69- inProgressData = ( parameter, task)
72+ inProgressData = ( parameter, ContinuousClock . now + debounceDuration , task)
7073 }
7174}
7275
7376extension Debouncer < Void > {
74- public init ( debounceDuration: Duration , _ makeCall: @escaping ( ) async -> Void ) {
77+ public init ( debounceDuration: Duration , _ makeCall: @Sendable @ escaping ( ) async -> Void ) {
7578 self . init ( debounceDuration: debounceDuration, combineResults: { _, _ in } , makeCall)
7679 }
7780
0 commit comments