From 838a3822a51338745bcce976cd44d24b9cfb637c Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Tue, 29 Sep 2020 12:56:52 -0400 Subject: [PATCH] Debounce storage calls on http intercept --- awx/ui_next/src/api/Base.js | 9 ++++-- awx/ui_next/src/util/debounce.js | 19 +++++++++++++ awx/ui_next/src/util/debounce.test.js | 40 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 awx/ui_next/src/util/debounce.js create mode 100644 awx/ui_next/src/util/debounce.test.js diff --git a/awx/ui_next/src/api/Base.js b/awx/ui_next/src/api/Base.js index c8d70203a2..cd0a76c1ec 100644 --- a/awx/ui_next/src/api/Base.js +++ b/awx/ui_next/src/api/Base.js @@ -2,6 +2,12 @@ import axios from 'axios'; import { SESSION_TIMEOUT_KEY } from '../constants'; import { encodeQueryString } from '../util/qs'; +import debounce from '../util/debounce'; + +const updateStorage = debounce((key, val) => { + window.localStorage.setItem(key, val); + window.dispatchEvent(new Event('storage')); +}, 500); const defaultHttp = axios.create({ xsrfCookieName: 'csrftoken', @@ -15,8 +21,7 @@ defaultHttp.interceptors.response.use(response => { const timeout = response?.headers['session-timeout']; if (timeout) { const timeoutDate = new Date().getTime() + timeout * 1000; - window.localStorage.setItem(SESSION_TIMEOUT_KEY, String(timeoutDate)); - window.dispatchEvent(new Event('storage')); + updateStorage(SESSION_TIMEOUT_KEY, String(timeoutDate)); } return response; }); diff --git a/awx/ui_next/src/util/debounce.js b/awx/ui_next/src/util/debounce.js new file mode 100644 index 0000000000..d2ab3441ca --- /dev/null +++ b/awx/ui_next/src/util/debounce.js @@ -0,0 +1,19 @@ +/** + * The debounce utility creates a debounced version of the provided + * function. The debounced function delays invocation until after + * the given time interval (milliseconds) has elapsed since the last + * time the function was called. This means that if you call the + * debounced function repeatedly, it will only run once after it + * stops being called. + */ +const debounce = (func, interval) => { + let timeout; + return (...args) => { + clearTimeout(timeout); + timeout = setTimeout(() => { + func(...args); + }, interval); + }; +}; + +export default debounce; diff --git a/awx/ui_next/src/util/debounce.test.js b/awx/ui_next/src/util/debounce.test.js new file mode 100644 index 0000000000..a5c448dcf5 --- /dev/null +++ b/awx/ui_next/src/util/debounce.test.js @@ -0,0 +1,40 @@ +import debounce from './debounce'; + +jest.useFakeTimers(); + +describe('debounce', () => { + test('it debounces', () => { + let count = 0; + const func = increment => { + count += increment; + }; + const debounced = debounce(func, 1000); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + expect(count).toEqual(0); + jest.advanceTimersByTime(1000); + expect(count).toEqual(2); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + jest.advanceTimersByTime(1000); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + jest.advanceTimersByTime(1000); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + debounced(2); + jest.advanceTimersByTime(1000); + expect(count).toEqual(8); + }); +});