@@ -262,112 +262,3 @@ class SearchInputElement extends HTMLInputElement {
262
262
}
263
263
}
264
264
` ` `
265
-
266
- ### Using signals to debounce or throttle methods
267
-
268
- _Debouncing_ or _Throttling_ are techniques whereby you delay an action for a fixed time period, discarding any events
269
- between them. These techniques are useful within UI as a way to delay an expensive operation like a network fetch or
270
- something CPU intensive like sorting many items. Consider a list filter input, that shows and hides thousands of items
271
- depending on if they match the text input.
272
-
273
- As debouncing & throttling are based on time, an ` AbortController` isn't needed. Timeouts are such a common pattern that
274
- ` AbortSignal .timeout ()` can be used as a quick way to create a signal that will abort after some time has passed.
275
-
276
- Throttling and debouncing are variations on the same broader concept of limiting the times an action gets executed. If
277
- you're calling a function 10 times in a row, at 50ms intervals, a throttle of 100ms would ensure that the action is only
278
- run every 100ms, whereas a debounce would defer each call until there hadn't been one for more 100ms or more. To
279
- illustrate this concept we can look at a timeline:
280
-
281
- ` ` `
282
- | ---- - | ---- - | ---- - | ---- - | ---- - | ---- - | ---- - | ---- - |
283
- Source 50 100 200 250 350 400
284
- throttle (100 ) 100 200 350
285
- debounce (100 ) 100 250 400
286
- ` ` `
287
-
288
- You can think of throttling as disregarding some calls but acting on others, whereas debounce waits for quiet periods.
289
- To throttle a method, you'll create the signal every time it is aborted, and execute the behavior when the timer has
290
- aborted:
291
-
292
- ` ` ` js
293
- class ListFilterInputElement extends HTMLInputElement {
294
- static define (tag = " list-filter-input" ) {
295
- customElements .define (tag, this , { extends: " input" })
296
- }
297
-
298
- connectedCallback () {
299
- this .addEventListener (" input" , this )
300
- }
301
-
302
- timeout = 100
303
-
304
- #throttleSignal = null
305
-
306
- handleEvent () {
307
- // Don't do anything if the timer has yet to time out
308
- if (this .#throttleSignal && ! this .#throttleSignal .aborted ) return
309
-
310
- // The time has been aborted, so make a new timer for next time
311
- this .#throttleSignal = AbortSignal .timeout (this .timeout )
312
-
313
- // Execute the action
314
- this .filer ()
315
- }
316
-
317
- filter () {
318
- for (const el of this .list .children ) {
319
- el .hidden = el .textContent .includes (this .input )
320
- }
321
- }
322
- }
323
- ` ` `
324
-
325
- _Debouncing_ would add a **delay** and so needs to act on the timeout happening, not some time after. Using the
326
- ` aborted` event can queue up work for when the timer ends:
327
-
328
- ` ` ` js
329
- class ListFilterInputElement extends HTMLInputElement {
330
- static define (tag = " list-filter-input" ) {
331
- customElements .define (tag, this , { extends: " input" })
332
- }
333
-
334
- connectedCallback () {
335
- this .addEventListener (" input" , this )
336
- }
337
-
338
- timeout = 100
339
-
340
- #debounceSignal = null
341
-
342
- async handleEvent () {
343
- // Don't do anything if the timer has run out
344
- if (this .#debounceSignal? .aborted ) return
345
-
346
- // Renew the signal
347
- this .#debounceSignal = AbortSignal .timeout (this .timeout )
348
-
349
- // Schedule work for after debouncement
350
- this .#debounceSignal .addEventListener (
351
- " abort" ,
352
- (event ) => {
353
- // Check to see that new work hasn't been scheduled
354
- if (event .target === this .#debounceSignal) {
355
- // Clear out the signal so new work can be schedule
356
- this .#debounceSignal = null
357
-
358
- // Execute the action
359
- this .filter ()
360
- }
361
- },
362
- { once: true }
363
- )
364
- }
365
-
366
- filter () {
367
- for (const el of this .list .children ) {
368
- el .hidden = el .textContent .includes (this .input )
369
- }
370
- }
371
- }
372
- ` ` `
373
-
0 commit comments