зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1364150 - Introduce debounce middleware; r=bgrins
MozReview-Commit-ID: Hu3rQ3iJHzP --HG-- extra : rebase_source : 1f3d8b079a930eca7e4e807d6833e60258ef2bcf
This commit is contained in:
Родитель
6fd9167b8e
Коммит
1b86a2bfab
|
@ -0,0 +1,96 @@
|
|||
/* 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 => {
|
||||
let 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;
|
||||
let doFunction = () => {
|
||||
clearTimeout(timeout);
|
||||
clearTimeout(maxTimeout);
|
||||
timeout = maxTimeout = null;
|
||||
cb();
|
||||
};
|
||||
|
||||
return () => {
|
||||
return new Promise(resolve => {
|
||||
let 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,
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'debounce.js',
|
||||
'history.js',
|
||||
'log.js',
|
||||
'promise.js',
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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";
|
||||
|
||||
const { BATCH_ACTIONS } = require("../constants");
|
||||
|
||||
function batchActions(batchedActions) {
|
||||
return {
|
||||
type: BATCH_ACTIONS,
|
||||
actions: batchedActions,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
batchActions
|
||||
};
|
|
@ -7,7 +7,6 @@
|
|||
"use strict";
|
||||
|
||||
const actionModules = [
|
||||
require("./enhancers"),
|
||||
require("./filters"),
|
||||
require("./messages"),
|
||||
require("./ui"),
|
||||
|
|
|
@ -10,7 +10,7 @@ const {
|
|||
prepareMessage
|
||||
} = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
|
||||
const { batchActions } = require("devtools/client/webconsole/new-console-output/actions/enhancers");
|
||||
const { batchActions } = require("devtools/client/shared/redux/middleware/debounce");
|
||||
const {
|
||||
MESSAGE_ADD,
|
||||
NETWORK_MESSAGE_UPDATE,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'enhancers.js',
|
||||
'filters.js',
|
||||
'index.js',
|
||||
'messages.js',
|
||||
|
|
|
@ -9,6 +9,7 @@ const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
|||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
|
||||
const { batchActions } = require("devtools/client/shared/redux/middleware/debounce");
|
||||
const { createContextMenu } = require("devtools/client/webconsole/new-console-output/utils/context-menu");
|
||||
const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
|
||||
|
||||
|
@ -172,7 +173,7 @@ NewConsoleOutputWrapper.prototype = {
|
|||
|
||||
dispatchMessagesAdd: function (messages) {
|
||||
const batchedActions = messages.map(message => actions.messageAdd(message));
|
||||
store.dispatch(actions.batchActions(batchedActions));
|
||||
store.dispatch(batchActions(batchedActions));
|
||||
},
|
||||
|
||||
dispatchMessagesClear: function () {
|
||||
|
@ -204,7 +205,7 @@ function batchedMessageAdd(action) {
|
|||
queuedActions.push(action);
|
||||
if (!throttledDispatchTimeout) {
|
||||
throttledDispatchTimeout = setTimeout(() => {
|
||||
store.dispatch(actions.batchActions(queuedActions));
|
||||
store.dispatch(batchActions(queuedActions));
|
||||
queuedActions = [];
|
||||
throttledDispatchTimeout = null;
|
||||
}, 50);
|
||||
|
|
|
@ -12,11 +12,13 @@ const {
|
|||
createStore
|
||||
} = require("devtools/client/shared/vendor/redux");
|
||||
const { thunk } = require("devtools/client/shared/redux/middleware/thunk");
|
||||
const {
|
||||
BATCH_ACTIONS
|
||||
} = require("devtools/client/shared/redux/middleware/debounce");
|
||||
const {
|
||||
MESSAGE_ADD,
|
||||
MESSAGES_CLEAR,
|
||||
REMOVED_MESSAGES_CLEAR,
|
||||
BATCH_ACTIONS,
|
||||
PREFS,
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
const { reducers } = require("./reducers/index");
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
debounceActions,
|
||||
} = require("devtools/client/shared/redux/middleware/debounce");
|
||||
|
||||
describe("Debounce Middleware", () => {
|
||||
let nextArgs = [];
|
||||
const fakeStore = {};
|
||||
const fakeNext = (...args) => {
|
||||
nextArgs.push(args);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
nextArgs = [];
|
||||
});
|
||||
|
||||
it("should pass the intercepted action to next", () => {
|
||||
const fakeAction = {
|
||||
type: "FAKE_ACTION"
|
||||
};
|
||||
|
||||
debounceActions()(fakeStore)(fakeNext)(fakeAction);
|
||||
|
||||
expect(nextArgs.length).toEqual(1);
|
||||
expect(nextArgs[0]).toEqual([fakeAction]);
|
||||
});
|
||||
|
||||
it("should debounce if specified", () => {
|
||||
const fakeAction = {
|
||||
type: "FAKE_ACTION",
|
||||
meta: {
|
||||
debounce: true
|
||||
}
|
||||
};
|
||||
|
||||
const executed = debounceActions(1, 1)(fakeStore)(fakeNext)(fakeAction);
|
||||
expect(nextArgs.length).toEqual(0);
|
||||
|
||||
return executed.then(() => {
|
||||
expect(nextArgs.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("should have no effect if no timeout", () => {
|
||||
const fakeAction = {
|
||||
type: "FAKE_ACTION",
|
||||
meta: {
|
||||
debounce: true
|
||||
}
|
||||
};
|
||||
|
||||
debounceActions()(fakeStore)(fakeNext)(fakeAction);
|
||||
expect(nextArgs.length).toEqual(1);
|
||||
expect(nextArgs[0]).toEqual([fakeAction]);
|
||||
});
|
||||
});
|
Загрузка…
Ссылка в новой задаче