perfect-debounce 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 - UnJS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # perfect-debounce
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+ [![Github Actions][github-actions-src]][github-actions-href]
6
+ [![Codecov][codecov-src]][codecov-href]
7
+
8
+ > An improved debounce function with Promise support.
9
+
10
+ - Well tested debounce implementation
11
+ - Native Promise support
12
+ - Avoid duplicate calls while promise is being resolved
13
+ - Configurable `trailing` and `leading` behavior
14
+
15
+ ## Usage
16
+
17
+ Install package:
18
+
19
+ ```sh
20
+ # npm
21
+ npm install perfect-debounce
22
+
23
+ # yarn
24
+ yarn install perfect-debounce
25
+
26
+ # pnpm
27
+ pnpm install perfect-debounce
28
+ ```
29
+
30
+ Import:
31
+
32
+ ```js
33
+ // ESM
34
+ import { debounce } from 'perfect-debounce'
35
+
36
+ // CommonJS
37
+ const { debounce } = require('perfect-debounce')
38
+ ```
39
+
40
+ Debounce function:
41
+
42
+ ```js
43
+ const debounced = debounce(async () => {
44
+ // Some heavy stuff
45
+ }, 25)
46
+ ```
47
+
48
+ When calling `debounced`, it will wait at least for `25ms` as configured before actually calling our function. This helps to avoid multiple calls.
49
+
50
+ To avoid initial wait, we can set `leading: true` option. It will cause function to be immediately called if there is no other call:
51
+
52
+ ```js
53
+ const debounced = debounce(async () => {
54
+ // Some heavy stuff
55
+ }, 25, { leading: true })
56
+ ```
57
+
58
+ If executing async function takes longer than debounce value, duplicate calls will be still prevented a last call will happen. To disable this behavior, we can set `trailing: false` option:
59
+
60
+ ```js
61
+ const debounced = debounce(async () => {
62
+ // Some heavy stuff
63
+ }, 25, { trailing: false })
64
+ ```
65
+
66
+ ## 💻 Development
67
+
68
+ - Clone this repository
69
+ - Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable` (use `npm i -g corepack` for Node.js < 16.10)
70
+ - Install dependencies using `yarn install`
71
+ - Run interactive tests using `yarn dev`
72
+
73
+ ## License
74
+
75
+ Made with 💛
76
+
77
+ Based on [sindresorhus/p-debounce](https://github.com/sindresorhus/p-debounce).
78
+
79
+ Published under [MIT License](./LICENSE).
80
+
81
+ <!-- Badges -->
82
+ [npm-version-src]: https://img.shields.io/npm/v/perfect-debounce?style=flat-square
83
+ [npm-version-href]: https://npmjs.com/package/perfect-debounce
84
+
85
+ [npm-downloads-src]: https://img.shields.io/npm/dm/perfect-debounce?style=flat-square
86
+ [npm-downloads-href]: https://npmjs.com/package/perfect-debounce
87
+
88
+ [github-actions-src]: https://img.shields.io/github/workflow/status/unjs/perfect-debounce/ci/main?style=flat-square
89
+ [github-actions-href]: https://github.com/unjs/perfect-debounce/actions?query=workflow%3Aci
90
+
91
+ [codecov-src]: https://img.shields.io/codecov/c/gh/unjs/perfect-debounce/main?style=flat-square
92
+ [codecov-href]: https://codecov.io/gh/unjs/perfect-debounce
package/dist/index.cjs ADDED
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const DEBOUNCE_DEFAULTS = {
6
+ trailing: true
7
+ };
8
+ function debounce(fn, wait, options = {}) {
9
+ options = { ...DEBOUNCE_DEFAULTS, ...options };
10
+ if (!Number.isFinite(wait)) {
11
+ throw new TypeError("Expected `wait` to be a finite number");
12
+ }
13
+ let leadingValue;
14
+ let timeout;
15
+ let resolveList = [];
16
+ let currentPromise;
17
+ let trailingArgs;
18
+ const applyFn = async (_this, args) => {
19
+ currentPromise = _applyPromised(fn, _this, args);
20
+ currentPromise.finally(() => {
21
+ currentPromise = null;
22
+ if (options.trailing && trailingArgs && !timeout) {
23
+ const promise = applyFn(_this, trailingArgs);
24
+ trailingArgs = null;
25
+ return promise;
26
+ }
27
+ });
28
+ return currentPromise;
29
+ };
30
+ return function(...args) {
31
+ if (currentPromise) {
32
+ if (options.trailing) {
33
+ trailingArgs = args;
34
+ }
35
+ return currentPromise;
36
+ }
37
+ return new Promise((resolve) => {
38
+ const shouldCallNow = !timeout && options.leading;
39
+ clearTimeout(timeout);
40
+ timeout = setTimeout(() => {
41
+ timeout = null;
42
+ const promise = options.leading ? leadingValue : applyFn(this, args);
43
+ for (const _resolve of resolveList) {
44
+ _resolve(promise);
45
+ }
46
+ resolveList = [];
47
+ }, wait);
48
+ if (shouldCallNow) {
49
+ leadingValue = applyFn(this, args);
50
+ resolve(leadingValue);
51
+ } else {
52
+ resolveList.push(resolve);
53
+ }
54
+ });
55
+ };
56
+ }
57
+ async function _applyPromised(fn, _this, args) {
58
+ return await fn.apply(_this, args);
59
+ }
60
+
61
+ exports.debounce = debounce;
@@ -0,0 +1,34 @@
1
+ interface DebounceOptions {
2
+ /**
3
+ Call the `fn` on the [leading edge of the timeout](https://css-tricks.com/debouncing-throttling-explained-examples/#article-header-id-1).
4
+ Meaning immediately, instead of waiting for `wait` milliseconds.
5
+ @default false
6
+ */
7
+ readonly leading?: boolean;
8
+ /**
9
+ Call the `fn` on trailing edge with last used arguments. Result of call is from previous call.
10
+ @default false
11
+ */
12
+ readonly trailing?: boolean;
13
+ }
14
+ /**
15
+ Debounce functions
16
+ @param fn - Promise-returning/async function to debounce.
17
+ @param wait - Milliseconds to wait before calling `fn`.
18
+ @returns A function that delays calling `fn` until after `wait` milliseconds have elapsed since the last time it was called.
19
+ @example
20
+ ```
21
+ import pDebounce from 'p-debounce';
22
+ const expensiveCall = async input => input;
23
+ const debouncedFn = pDebounce(expensiveCall, 200);
24
+ for (const number of [1, 2, 3]) {
25
+ console.log(await debouncedFn(number));
26
+ }
27
+ //=> 3
28
+ //=> 3
29
+ //=> 3
30
+ ```
31
+ */
32
+ declare function debounce<ArgumentsType extends unknown[], ReturnType>(fn: (...args: ArgumentsType) => PromiseLike<ReturnType> | ReturnType, wait: number, options?: DebounceOptions): (...args: any[]) => Promise<unknown>;
33
+
34
+ export { DebounceOptions, debounce };
package/dist/index.mjs ADDED
@@ -0,0 +1,57 @@
1
+ const DEBOUNCE_DEFAULTS = {
2
+ trailing: true
3
+ };
4
+ function debounce(fn, wait, options = {}) {
5
+ options = { ...DEBOUNCE_DEFAULTS, ...options };
6
+ if (!Number.isFinite(wait)) {
7
+ throw new TypeError("Expected `wait` to be a finite number");
8
+ }
9
+ let leadingValue;
10
+ let timeout;
11
+ let resolveList = [];
12
+ let currentPromise;
13
+ let trailingArgs;
14
+ const applyFn = async (_this, args) => {
15
+ currentPromise = _applyPromised(fn, _this, args);
16
+ currentPromise.finally(() => {
17
+ currentPromise = null;
18
+ if (options.trailing && trailingArgs && !timeout) {
19
+ const promise = applyFn(_this, trailingArgs);
20
+ trailingArgs = null;
21
+ return promise;
22
+ }
23
+ });
24
+ return currentPromise;
25
+ };
26
+ return function(...args) {
27
+ if (currentPromise) {
28
+ if (options.trailing) {
29
+ trailingArgs = args;
30
+ }
31
+ return currentPromise;
32
+ }
33
+ return new Promise((resolve) => {
34
+ const shouldCallNow = !timeout && options.leading;
35
+ clearTimeout(timeout);
36
+ timeout = setTimeout(() => {
37
+ timeout = null;
38
+ const promise = options.leading ? leadingValue : applyFn(this, args);
39
+ for (const _resolve of resolveList) {
40
+ _resolve(promise);
41
+ }
42
+ resolveList = [];
43
+ }, wait);
44
+ if (shouldCallNow) {
45
+ leadingValue = applyFn(this, args);
46
+ resolve(leadingValue);
47
+ } else {
48
+ resolveList.push(resolve);
49
+ }
50
+ });
51
+ };
52
+ }
53
+ async function _applyPromised(fn, _this, args) {
54
+ return await fn.apply(_this, args);
55
+ }
56
+
57
+ export { debounce };
package/package.json CHANGED
@@ -1,5 +1,41 @@
1
1
  {
2
- "name": "perfect-debounce",
3
- "version": "0.0.0",
4
- "license": "MIT"
5
- }
2
+ "name": "perfect-debounce",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "repository": "unjs/perfect-debounce",
6
+ "license": "MIT",
7
+ "sideEffects": false,
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "main": "./dist/index.cjs",
16
+ "module": "./dist/index.mjs",
17
+ "types": "./dist/index.d.ts",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "unbuild",
23
+ "dev": "vitest dev",
24
+ "lint": "eslint --ext .ts,.js,.mjs,.cjs .",
25
+ "prepack": "unbuild",
26
+ "release": "yarn test && standard-version && git push --follow-tags && npm publish",
27
+ "test": "vitest run --coverage"
28
+ },
29
+ "dependencies": {},
30
+ "devDependencies": {
31
+ "@nuxtjs/eslint-config-typescript": "latest",
32
+ "c8": "latest",
33
+ "eslint": "latest",
34
+ "in-range": "^3.0.0",
35
+ "standard-version": "latest",
36
+ "time-span": "^5.0.0",
37
+ "typescript": "latest",
38
+ "unbuild": "latest",
39
+ "vitest": "latest"
40
+ }
41
+ }