-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #522 from NullVoxPopuli/debounce
feat: new util: debounce
- Loading branch information
Showing
8 changed files
with
162 additions
and
7 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 |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
# compiled output | ||
dist/ | ||
tmp/ | ||
tsconfig.tsbuildinfo | ||
|
||
# dependencies | ||
node_modules/ | ||
|
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,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; | ||
}); | ||
} |
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,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'); | ||
}); | ||
}); | ||
}); |
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 |
---|---|---|
|
@@ -37,5 +37,8 @@ | |
"app/**/*", | ||
"tests/**/*", | ||
"types/**/*" | ||
], | ||
"references": [ | ||
{ "path": "../../ember-resources" } | ||
] | ||
} |