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