Skip to content

Commit

Permalink
Merge pull request #522 from NullVoxPopuli/debounce
Browse files Browse the repository at this point in the history
feat: new util: debounce
  • Loading branch information
NullVoxPopuli authored Jun 11, 2022
2 parents 718dfa6 + 357e266 commit 64da51a
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# compiled output
dist/
tmp/
tsconfig.tsbuildinfo

# dependencies
node_modules/
Expand Down
4 changes: 4 additions & 0 deletions ember-resources/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"./util/map": "./dist/util/map.js",
"./util/helper": "./dist/util/helper.js",
"./util/remote-data": "./dist/util/remote-data.js",
"./util/debounce": "./dist/util/debounce.js",
"./util/function": "./dist/util/function.js",
"./util/function-resource": "./dist/util/function-resource.js",
"./util/ember-concurrency": "./dist/util/ember-concurrency.js",
Expand Down Expand Up @@ -42,6 +43,9 @@
"util/helper": [
"dist/util/helper.d.ts"
],
"util/debounce": [
"dist/util/debounce.d.ts"
],
"util/remote-data": [
"dist/util/remote-data.d.ts"
],
Expand Down
72 changes: 72 additions & 0 deletions ember-resources/src/util/debounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { tracked } from '@glimmer/tracking';

import { resource } from './function-resource';

class TrackedValue<T> {
@tracked value: T | undefined;
}

/**
* A utility for debouncing high-frequency updates.
* The returned value will only be updated every `ms` and is
* initially undefined.
*
* This can be useful when a user's typing is updating a tracked
* property and you want to derive data less frequently than on
* each keystroke.
*
* Note that this utility requires the @use decorator
* (debounce could be implemented without the need for the @use decorator
* but the current implementation is 8 lines)
*
* @example
* ```js
* import Component from '@glimmer/component';
* import { tracked } from '@glimmer/tracking';
* import { debounce } from 'ember-resources/util/debounce';
*
* const delay = 100; // ms
*
* class Demo extends Component {
* @tracked userInput = '';
*
* @use debouncedInput = debounce(delay, () => this.userInput);
* }
* ```
*
* @example
* This could be further composed with [[RemoteData]]
* ```js
* import Component from '@glimmer/component';
* import { tracked } from '@glimmer/tracking';
* import { debounce } from 'ember-resources/util/debounce';
* import { RemoteData } from 'ember-resources/util/remote-data';
*
* const delay = 100; // ms
*
* class Demo extends Component {
* @tracked userInput = '';
*
* @use debouncedInput = debounce(delay, () => this.userInput);
*
* @use search = RemoteData(() => `https://my.domain/search?q=${this.debouncedInput}`);
* }
* ```
*
* @param {number} ms delay in milliseconds to wait before updating the returned value
* @param {() => Value} thunk function that returns the value to debounce
*/
export function debounce<Value = unknown>(ms: number, thunk: () => Value) {
let lastValue: Value;
let timer: number;
let state = new TrackedValue();

return resource(({ on }) => {
lastValue = thunk();

on.cleanup(() => timer && clearTimeout(timer));
timer = setTimeout(() => (state.value = lastValue), ms);

return state.value;
});
}
4 changes: 4 additions & 0 deletions ember-resources/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"compilerOptions": {
// So that the test app's type checking doesn't break when we change types
"composite": true,

// Path resolution
"baseUrl": "./src",
"moduleResolution": "node",
// We only use tsc for type checking and declaration output
"emitDeclarationOnly": false,
"declarationDir": "./dist",
"declaration": true,
"declarationMap": true,
// Build settings
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@commitlint/cli": "^13.1.0",
"@commitlint/config-conventional": "^13.1.0",
"@nullvoxpopuli/eslint-configs": "^2.2.19",
"concurrency": "^0.1.4",
"concurrently": "^7.2.1",
"eslint": "^7.32.0",
"loader.js": "^4.7.0",
"prettier": "^2.6.2",
Expand All @@ -41,7 +41,9 @@
"mustache": "ember-cli -> testem -> consolidate -> mustache is ancient"
},
"peerDependencyRules": {
"ignoreMissing": ["msw"],
"ignoreMissing": [
"msw"
],
"allowedVersions": {
"typescript": "*"
}
Expand Down
31 changes: 26 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions testing/ember-app/tests/utils/debounce/js-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { tracked } from '@glimmer/tracking';
import { setOwner } from '@ember/application';
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

import { debounce } from 'ember-resources/util/debounce';
import { use } from 'ember-resources/util/function-resource';

module('Utils | debounce | js', function (hooks) {
setupTest(hooks);

let someTime = (ms = 25) => new Promise((resolve) => setTimeout(resolve, ms));

module('debounce', function () {
test('works with @use', async function (assert) {
class Test {
@tracked data = '';

@use text = debounce(100, () => this.data);
}

let test = new Test();

setOwner(test, this.owner);

assert.strictEqual(test.text, undefined);

test.data = 'b';
await someTime();
assert.strictEqual(test.text, undefined);
test.data = 'bo';
await someTime();
assert.strictEqual(test.text, undefined);
test.data = 'boo';
await someTime();
assert.strictEqual(test.text, undefined);

await someTime(110);
assert.strictEqual(test.text, 'boo');

test.data = 'boop';
assert.strictEqual(test.text, 'boo');

await someTime(110);
assert.strictEqual(test.text, 'boop');
});
});
});
3 changes: 3 additions & 0 deletions testing/ember-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,8 @@
"app/**/*",
"tests/**/*",
"types/**/*"
],
"references": [
{ "path": "../../ember-resources" }
]
}

0 comments on commit 64da51a

Please sign in to comment.