Skip to content

Commit ad364ff

Browse files
committed
fix: bug when throttled function is sync
fix #11
1 parent 947f638 commit ad364ff

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

src/index.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class Delay {
3232
}
3333

3434
function throttle<Args: Array<any>, Value>(
35-
fn: (...args: Args) => Promise<Value>,
35+
fn: (...args: Args) => Value | Promise<Value>,
3636
_wait: ?number,
3737
options: {
3838
getNextArgs?: (args0: Args, args1: Args) => Args,
@@ -52,10 +52,16 @@ function throttle<Args: Array<any>, Value>(
5252

5353
function invoke(): Promise<Value> {
5454
const args = nextArgs
55+
// istanbul ignore next
5556
if (!args) throw new Error('unexpected error: nextArgs is null')
5657
nextInvocation = null
5758
nextArgs = null
58-
const result = fn(...args)
59+
let result
60+
try {
61+
result = Promise.resolve(fn(...args))
62+
} catch (error) {
63+
result = Promise.reject(error)
64+
}
5965
lastInvocationDone = result.catch(() => {})
6066
delay = new Delay(lastInvocationDone, wait)
6167
return result

test/index.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,43 @@ describe('throttle', () => {
7272
getNextArgs: () => (null: any),
7373
})
7474
fn(1)
75-
expect(() => fn(1)).to.throw()
75+
expect(() => fn(1)).to.throw('unexpected error: nextArgs is null')
76+
})
77+
it('works with sync function', async function(): Promise<void> {
78+
const foo = sinon.spy(
79+
(a: number, wait?: number): number => {
80+
if (a < 0) throw new Error()
81+
return a * 2
82+
}
83+
)
84+
const fn = throttle(foo, 100)
85+
let promises = [fn(1), fn(2), fn(3)].map(wrapPromise)
86+
for (let promise of promises) assert(promise.isPending())
87+
88+
await clock.tickAsync(1)
89+
for (let promise of promises) expect(promise.value()).to.equal(6)
90+
expect(foo.args).to.deep.equal([[3]])
91+
92+
promises = [fn(4), fn(-4), fn(5)].map(wrapPromise)
93+
promises.forEach(p => p.catch(() => {}))
94+
await clock.tickAsync(40)
95+
for (let promise of promises) assert(promise.isPending())
96+
97+
await clock.tickAsync(60)
98+
for (let promise of promises) expect(promise.value()).to.equal(10)
99+
100+
expect(foo.args).to.deep.equal([[3], [5]])
101+
102+
await clock.tickAsync(1000)
103+
expect(foo.args).to.deep.equal([[3], [5]])
104+
105+
promises = [fn(1), fn(2), fn(3)].map(wrapPromise)
106+
await clock.tickAsync(1)
107+
for (let promise of promises) expect(promise.value()).to.equal(6)
108+
109+
promises = [fn(-10)].map(wrapPromise)
110+
await clock.tickAsync(100)
111+
assert(promises[0].isRejected())
76112
})
77113
it('works', async function(): Promise<void> {
78114
const foo = sinon.spy(

0 commit comments

Comments
 (0)