-
Notifications
You must be signed in to change notification settings - Fork 27
/
index.js
66 lines (53 loc) · 1.52 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* global setTimeout, clearTimeout */
module.exports = function debounce (fn, wait = 0, options = {}) {
let lastCallAt
let deferred
let timer
let pendingArgs = []
return function debounced (...args) {
const currentWait = getWait(wait)
const currentTime = new Date().getTime()
const isCold = !lastCallAt || (currentTime - lastCallAt) > currentWait
lastCallAt = currentTime
if (isCold && options.leading) {
return options.accumulate
? Promise.resolve(fn.call(this, [args])).then(result => result[0])
: Promise.resolve(fn.call(this, ...args))
}
if (deferred) {
clearTimeout(timer)
} else {
deferred = defer()
}
pendingArgs.push(args)
timer = setTimeout(flush.bind(this), currentWait)
if (options.accumulate) {
const argsIndex = pendingArgs.length - 1
return deferred.promise.then(results => results[argsIndex])
}
return deferred.promise
}
function flush () {
const thisDeferred = deferred
clearTimeout(timer)
Promise.resolve(
options.accumulate
? fn.call(this, pendingArgs)
: fn.apply(this, pendingArgs[pendingArgs.length - 1])
)
.then(thisDeferred.resolve, thisDeferred.reject)
pendingArgs = []
deferred = null
}
}
function getWait (wait) {
return (typeof wait === 'function') ? wait() : wait
}
function defer () {
const deferred = {}
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve
deferred.reject = reject
})
return deferred
}