debounce.js (2470B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 "use strict"; 5 6 /** 7 * Redux middleware for debouncing actions. 8 * 9 * Schedules actions with { meta: { debounce: true } } to be delayed 10 * by wait milliseconds. If another action is fired during this 11 * time-frame both actions are inserted into a queue and delayed. 12 * Maximum delay is defined by maxWait argument. 13 * 14 * Handling more actions at once results in better performance since 15 * components need to be re-rendered less often. 16 * 17 * @param string wait Wait for specified amount of milliseconds 18 * before executing an action. The time is used 19 * to collect more actions and handle them all 20 * at once. 21 * @param string maxWait Max waiting time. It's used in case of 22 * a long stream of actions. 23 */ 24 function debounceActions(wait, maxWait) { 25 let queuedActions = []; 26 27 return () => next => { 28 const debounced = debounce( 29 () => { 30 next(batchActions(queuedActions)); 31 queuedActions = []; 32 }, 33 wait, 34 maxWait 35 ); 36 37 return action => { 38 if (!action.meta || !action.meta.debounce) { 39 return next(action); 40 } 41 42 if (!wait || !maxWait) { 43 return next(action); 44 } 45 46 if (action.type == BATCH_ACTIONS) { 47 queuedActions.push(...action.actions); 48 } else { 49 queuedActions.push(action); 50 } 51 52 return debounced(); 53 }; 54 }; 55 } 56 57 function debounce(cb, wait, maxWait) { 58 let timeout, maxTimeout; 59 const doFunction = () => { 60 clearTimeout(timeout); 61 clearTimeout(maxTimeout); 62 timeout = maxTimeout = null; 63 cb(); 64 }; 65 66 return () => { 67 return new Promise(resolve => { 68 const onTimeout = () => { 69 doFunction(); 70 resolve(); 71 }; 72 73 clearTimeout(timeout); 74 75 timeout = setTimeout(onTimeout, wait); 76 if (!maxTimeout) { 77 maxTimeout = setTimeout(onTimeout, maxWait); 78 } 79 }); 80 }; 81 } 82 83 const BATCH_ACTIONS = Symbol("BATCH_ACTIONS"); 84 85 /** 86 * Action creator for action-batching. 87 */ 88 function batchActions(batchedActions, debounceFlag = true) { 89 return { 90 type: BATCH_ACTIONS, 91 meta: { debounce: debounceFlag }, 92 actions: batchedActions, 93 }; 94 } 95 96 module.exports = { 97 BATCH_ACTIONS, 98 batchActions, 99 debounceActions, 100 };