Last active
May 17, 2017 08:03
-
-
Save rcharlton/1c3f47c451da3ad018a80169d83019d3 to your computer and use it in GitHub Desktop.
A super-simple invocation rate throttler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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