Bug 1416161 - Using redux-batched-subscribe + unstable_batchedUpdates to reduce Redux’s subscribed notifications r?honza
MozReview-Commit-ID: 2ooo35vy4fB
--- a/devtools/client/netmonitor/src/utils/create-store.js
+++ b/devtools/client/netmonitor/src/utils/create-store.js
@@ -1,16 +1,22 @@
/* 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 Services = require("Services");
-const { applyMiddleware, createStore } = require("devtools/client/shared/vendor/redux");
+const { unstable_batchedUpdates } = require("devtools/client/shared/vendor/react-dom"); // eslint-disable-line
+const {
+ applyMiddleware,
+ createStore,
+ compose,
+} = require("devtools/client/shared/vendor/redux");
+const { batchedSubscribe } = require("../utils/redux-batched-subscribe");
// Middleware
const batching = require("../middleware/batching");
const prefs = require("../middleware/prefs");
const thunk = require("../middleware/thunk");
const recording = require("../middleware/recording");
// Reducers
@@ -33,25 +39,27 @@ function configureStore(connector) {
requests: new Requests(),
sort: new Sort(),
timingMarkers: new TimingMarkers(),
ui: new UI({
columns: getColumnState()
}),
};
- // Prepare middleware.
- let middleware = applyMiddleware(
- thunk,
- prefs,
- batching,
- recording(connector)
+ let enhancer = compose(
+ applyMiddleware(
+ thunk,
+ prefs,
+ batching,
+ recording(connector),
+ ),
+ batchedSubscribe(unstable_batchedUpdates),
);
- return createStore(rootReducer, initialState, middleware);
+ return createStore(rootReducer, initialState, enhancer);
}
// Helpers
/**
* Get column state from preferences.
*/
function getColumnState() {
--- a/devtools/client/netmonitor/src/utils/moz.build
+++ b/devtools/client/netmonitor/src/utils/moz.build
@@ -8,12 +8,13 @@ DevToolsModules(
'filter-autocomplete-provider.js',
'filter-predicates.js',
'filter-text-utils.js',
'format-utils.js',
'l10n.js',
'mdn-utils.js',
'menu.js',
'prefs.js',
+ 'redux-batched-subscribe.js',
'request-utils.js',
'sort-predicates.js',
'sort-utils.js'
)
new file mode 100644
--- /dev/null
+++ b/devtools/client/netmonitor/src/utils/redux-batched-subscribe.js
@@ -0,0 +1,75 @@
+/* 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";
+
+function batchedSubscribe(batch) {
+ if (typeof batch !== "function") {
+ throw new Error("Expected batch to be a function.");
+ }
+
+ let currentListeners = [];
+ let nextListeners = currentListeners;
+
+ function ensureCanMutateNextListeners() {
+ if (nextListeners === currentListeners) {
+ nextListeners = currentListeners.slice();
+ }
+ }
+
+ function subscribe(listener) {
+ if (typeof listener !== "function") {
+ throw new Error("Expected listener to be a function.");
+ }
+
+ let isSubscribed = true;
+
+ ensureCanMutateNextListeners();
+ nextListeners.push(listener);
+
+ return function unsubscribe() {
+ if (!isSubscribed) {
+ return;
+ }
+
+ isSubscribed = false;
+
+ ensureCanMutateNextListeners();
+ const index = nextListeners.indexOf(listener);
+ nextListeners.splice(index, 1);
+ };
+ }
+
+ function notifyListeners() {
+ const listeners = currentListeners = nextListeners;
+ for (let i = 0; i < listeners.length; i++) {
+ listeners[i]();
+ }
+ }
+
+ function notifyListenersBatched() {
+ batch(notifyListeners);
+ }
+
+ return next => (...args) => {
+ const store = next(...args);
+ const subscribeImmediate = store.subscribe;
+
+ function dispatch(...dispatchArgs) {
+ const res = store.dispatch(...dispatchArgs);
+ notifyListenersBatched();
+ return res;
+ }
+
+ return Object.assign({}, store, {
+ dispatch,
+ subscribe,
+ subscribeImmediate,
+ });
+ };
+}
+
+module.exports = {
+ batchedSubscribe,
+};