From 89fb2001f3308ad3006bf34c8224b830f4b61ddd Mon Sep 17 00:00:00 2001
From: Ankur Patel <ankur.patel@ymail.com>
Date: Sun, 26 Mar 2017 11:41:52 -0400
Subject: [PATCH] Adding debounce and delay functions

---
 README.md            | 27 +++++++++++++++++++++++++++
 Sources/Dollar.swift | 25 +++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/README.md b/README.md
index ba19d4fa..16042feb 100644
--- a/README.md
+++ b/README.md
@@ -127,6 +127,33 @@ $.cycle([1, 2, 3], 2) {
 123123
 ```
 
+### delay - `$.delay`
+
+Delays the execution of a function by the specified DispatchTimeInterval
+
+```swift
+$.delay(by: .seconds(2)) {
+  print("Hello delayed by 2 seconds")
+}
+=> "Hello delayed by 2 seconds"
+```
+
+### debounce - `$.debounce`
+
+Debounce a function such that the function is only invoked once no matter how many times it is called within the delayBy interval
+
+```swift
+let printQueue = $.debounce(delayBy: .seconds(1)) {
+    print("Hello Queue!")
+}
+for _ in 0...9 {
+    printQueue()
+}
+$.delay(by: .seconds(2), printQueue)
+=> "Hello Queue!"
+=> "Hello Queue!"
+```
+
 ### difference - `$.difference`
 
 Creates an array excluding all values of the provided arrays
diff --git a/Sources/Dollar.swift b/Sources/Dollar.swift
index fa47c67a..739fb672 100644
--- a/Sources/Dollar.swift
+++ b/Sources/Dollar.swift
@@ -220,6 +220,31 @@ open class $ {
         }
     }
 
+    /// Delays the execution of a function by the specified DispatchTimeInterval
+    ///
+    /// - parameter by: interval to delay the execution of the function by
+    /// - parameter queue: Queue to run the function on. Defaults to main queue
+    /// - parameter function: function to execute
+    open class func delay(by interval: DispatchTimeInterval, queue: DispatchQueue = .main, _ function: @escaping () -> Void) {
+        queue.asyncAfter(deadline: .now() + interval, execute: function)
+    }
+
+    /// Debounce a function such that the function is only invoked once no matter how many times
+    /// it is called within the delayBy interval
+    ///
+    /// - parameter delayBy: interval to delay the execution of the function by
+    /// - parameter queue: Queue to run the function on. Defaults to main queue
+    /// - parameter function: function to execute
+    /// - returns: Function that is debounced and will only invoke once within the delayBy interval
+    open class func debounce(delayBy: DispatchTimeInterval, queue: DispatchQueue = .main, _ function: @escaping (() -> Void)) -> () -> Void {
+        var currentWorkItem: DispatchWorkItem?
+        return {
+            currentWorkItem?.cancel()
+            currentWorkItem = DispatchWorkItem { function() }
+            queue.asyncAfter(deadline: .now() + delayBy, execute: currentWorkItem!)
+        }
+    }
+
     /// Creates an array excluding all values of the provided arrays in order
     ///
     /// - parameter arrays: The arrays to difference between.