-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
154 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { debounce } from './debounce' | ||
import { times } from './times' | ||
import { wait } from './wait' | ||
|
||
test('表现正常', async () => { | ||
const fn: (x: number, y: number) => number = jest.fn().mockImplementation((x: number, y: number) => x + y) | ||
|
||
const debouncedFn = debounce(fn, 500) | ||
|
||
times(10000, () => debouncedFn(1, 2)) | ||
|
||
await wait(550) | ||
|
||
expect(fn).toBeCalledTimes(1) | ||
|
||
times(10000, () => debouncedFn(1, 2)) | ||
|
||
await wait(550) | ||
|
||
expect(fn).toBeCalledTimes(2) | ||
}) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { AnyFunction } from './enhanceType' | ||
|
||
/** | ||
* 创建一个去抖函数,将触发频繁的事件合并成一次执行。 | ||
* | ||
* 该函数被调用后,计时 `wait` 毫秒后调用 `fn` 函数。 | ||
* 若在 `wait` 毫秒内该函数再次被调用,则重新开始计时。 | ||
* | ||
* 一个应用场景:监听输入框的 `input` 事件发起网络请求。 | ||
* | ||
* @param fn 要去抖的函数 | ||
* @param wait 需要等待的毫秒数 | ||
* @returns 返回去抖后的函数 | ||
* @example | ||
* ```ts | ||
* document.querySelector('#input').oninput = debounce( | ||
* e => { | ||
* console.log(e.target.value) | ||
* }, | ||
* 500, | ||
* ) | ||
* ``` | ||
*/ | ||
export function debounce<T extends AnyFunction>(fn: T, wait: number): (...args: Parameters<T>) => void { | ||
let timer: NodeJS.Timeout | null = null | ||
|
||
return function (this: any) { | ||
if (timer) { | ||
clearTimeout(timer) | ||
} | ||
timer = setTimeout( | ||
() => fn.apply(this, arguments as any), | ||
wait, | ||
) | ||
} | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { throttle } from './throttle' | ||
import { wait } from './wait' | ||
|
||
test('表现正常', async () => { | ||
const fn: (x: number, y: number) => number = jest.fn().mockImplementation((x: number, y: number) => x + y) | ||
|
||
const throttledFn = throttle(fn, 500) | ||
|
||
expect(fn).toBeCalledTimes(0) | ||
|
||
throttledFn(1, 2) | ||
|
||
expect(fn).toBeCalledTimes(1) | ||
|
||
throttledFn(1, 2) | ||
|
||
expect(fn).toBeCalledTimes(1) | ||
|
||
await wait(400) | ||
|
||
expect(fn).toBeCalledTimes(1) | ||
|
||
await wait(200) | ||
|
||
expect(fn).toBeCalledTimes(2) | ||
}) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { AnyFunction } from './enhanceType' | ||
|
||
/** | ||
* 创建一个节流函数,给函数设置固定的执行速率。 | ||
* | ||
* - 该函数首次被调用时,会立即调用 `fn` 函数,并记录首次调用时间。 | ||
* - 该函数第二次被调用时: | ||
* - 如果该次调用时间在首次调用时间的 `wait` 区间内,`timer = setTimeout(操作, 时间差)`; | ||
* - 该函数再次被调用时: | ||
* - 如果该次调用时间在首次调用时间的 `wait` 区间内,什么都不做; | ||
* - 否则,清除首次调用时间和计时器,回到第一步。 | ||
* - 否则,清除首次调用时间,回到第一步。 | ||
* | ||
* 一个应用场景:监听窗口的 `resize` 事件响应相关操作。 | ||
* | ||
* @param fn 要节流的函数 | ||
* @param wait 需要等待的毫秒数 | ||
* @returns 返回节流后的函数 | ||
* @example | ||
* ```ts | ||
* window.addEventListener( | ||
* 'resize', | ||
* throttle( | ||
* () => console.log('窗口大小改变后的操作'), | ||
* 1000, | ||
* ), | ||
* ) | ||
* ``` | ||
*/ | ||
export function throttle<T extends AnyFunction>(fn: T, wait: number): (...args: Parameters<T>) => void { | ||
let timer: NodeJS.Timeout | null = null | ||
let lastTime: number | null = null | ||
|
||
return function (this: any) { | ||
const currentTime = new Date().getTime() | ||
|
||
const action = () => { | ||
lastTime = currentTime | ||
fn.apply(this, arguments as any) | ||
} | ||
|
||
// 首次调用 | ||
if (!lastTime) { | ||
action() | ||
} | ||
|
||
// 第二次调用 | ||
else if (!timer) { | ||
if (currentTime < lastTime + wait) { | ||
timer = setTimeout( | ||
() => { | ||
fn.apply(this, arguments as any) | ||
}, | ||
lastTime + wait - currentTime, | ||
) | ||
} else { | ||
action() | ||
} | ||
} | ||
|
||
// 再次调用 | ||
else { | ||
if (currentTime > lastTime + wait) { | ||
timer = null | ||
action() | ||
} | ||
} | ||
} | ||
} |