Skip to content

Instantly share code, notes, and snippets.

@rcharlton
Last active May 17, 2017 08:03
Show Gist options
  • Save rcharlton/1c3f47c451da3ad018a80169d83019d3 to your computer and use it in GitHub Desktop.
Save rcharlton/1c3f47c451da3ad018a80169d83019d3 to your computer and use it in GitHub Desktop.
A super-simple invocation rate throttler
/**
Manages the rate at which a closure is repeatedly invoked.
*/
public class Throttle {
/// The minimum time interval between executions.
private let period: TimeInterval
/// The closure to execute.
private let closure: () -> Void
/// Date of last invocation.
private var date = Date.distantPast
/**
Initialise a new throttled closure.
- parameter rate: the maximum number of invocations each second.
- parameter closure: the closure to execute.
*/
public init(rate: Double = 4, closure: @escaping () -> Void) {
self.period = 1 / rate
self.closure = closure
}
/**
Invoke the stored closure at the next permitted time.
*/
public func invoke() {
let nowDispatchTime = DispatchTime.now()
let nowDate = Date()
let elapsed = -date.timeIntervalSince(nowDate)
guard elapsed > 0 else {
// A future invocation is alreaady scheduled.
return
}
let remaining = period - elapsed
if remaining <= 0 {
date = nowDate
closure()
} else {
date += remaining
DispatchQueue.main.asyncAfter(
deadline: nowDispatchTime + remaining,
execute: closure)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment