[REF] web: sort by ASC order core/utils/timing
Part-of: odoo/odoo#112913
This commit is contained in:
@@ -1,58 +1,8 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
|
||||
import { onWillUnmount, useComponent } from "@odoo/owl";
|
||||
|
||||
/**
|
||||
* Creates a version of the function where only the last call between two
|
||||
* animation frames is executed before the browser's next repaint. This
|
||||
* effectively throttles the function to the display's refresh rate.
|
||||
* NB: The first call is always called immediately (leading edge).
|
||||
*
|
||||
* @template {Function} T
|
||||
* @param {T} func the function to throttle
|
||||
* @returns {T & { cancel: () => void }} the throttled function
|
||||
*/
|
||||
export function throttleForAnimation(func) {
|
||||
let handle = null;
|
||||
const calls = new Set();
|
||||
const funcName = func.name ? `${func.name} (throttleForAnimation)` : "throttleForAnimation";
|
||||
const pending = () => {
|
||||
if (calls.size) {
|
||||
handle = browser.requestAnimationFrame(pending);
|
||||
const { args, resolve } = [...calls].pop();
|
||||
calls.clear();
|
||||
Promise.resolve(func.apply(this, args)).then(resolve);
|
||||
} else {
|
||||
handle = null;
|
||||
}
|
||||
};
|
||||
return Object.assign(
|
||||
{
|
||||
/** @type {any} */
|
||||
[funcName](...args) {
|
||||
return new Promise((resolve) => {
|
||||
const isNew = handle === null;
|
||||
if (isNew) {
|
||||
handle = browser.requestAnimationFrame(pending);
|
||||
Promise.resolve(func.apply(this, args)).then(resolve);
|
||||
} else {
|
||||
calls.add({ args, resolve });
|
||||
}
|
||||
});
|
||||
},
|
||||
}[funcName],
|
||||
{
|
||||
cancel() {
|
||||
browser.cancelAnimationFrame(handle);
|
||||
calls.clear();
|
||||
handle = null;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new debounced version of the passed function (func)
|
||||
* which will postpone its execution until after 'delay' milliseconds
|
||||
@@ -103,24 +53,6 @@ export function debounce(func, delay, immediate = false) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook that returns a debounced version of the given function, and cancels
|
||||
* the potential pending execution on willUnmount.
|
||||
* @see debounce
|
||||
* @template {Function} T
|
||||
* @param {T} callback
|
||||
* @param {number | "animationFrame"} delay
|
||||
* @param {boolean} [immediate=false] whether the function should be called on
|
||||
* the leading edge instead of the trailing edge.
|
||||
* @returns {T & { cancel: () => void }}
|
||||
*/
|
||||
export function useDebounced(callback, delay, immediate = false) {
|
||||
const component = useComponent();
|
||||
const debounced = debounce(callback.bind(component), delay, immediate);
|
||||
onWillUnmount(() => debounced.cancel());
|
||||
return debounced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that calls recursively a request to an animation frame.
|
||||
* Useful to call a function repetitively, until asked to stop, that needs constant rerendering.
|
||||
@@ -144,3 +76,72 @@ export function setRecurringAnimationFrame(callback) {
|
||||
|
||||
return stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a version of the function where only the last call between two
|
||||
* animation frames is executed before the browser's next repaint. This
|
||||
* effectively throttles the function to the display's refresh rate.
|
||||
* NB: The first call is always called immediately (leading edge).
|
||||
*
|
||||
* @template {Function} T
|
||||
* @param {T} func the function to throttle
|
||||
* @returns {T & { cancel: () => void }} the throttled function
|
||||
*/
|
||||
export function throttleForAnimation(func) {
|
||||
let handle = null;
|
||||
const calls = new Set();
|
||||
const funcName = func.name ? `${func.name} (throttleForAnimation)` : "throttleForAnimation";
|
||||
const pending = () => {
|
||||
if (calls.size) {
|
||||
handle = browser.requestAnimationFrame(pending);
|
||||
const { args, resolve } = [...calls].pop();
|
||||
calls.clear();
|
||||
Promise.resolve(func.apply(this, args)).then(resolve);
|
||||
} else {
|
||||
handle = null;
|
||||
}
|
||||
};
|
||||
return Object.assign(
|
||||
{
|
||||
/** @type {any} */
|
||||
[funcName](...args) {
|
||||
return new Promise((resolve) => {
|
||||
const isNew = handle === null;
|
||||
if (isNew) {
|
||||
handle = browser.requestAnimationFrame(pending);
|
||||
Promise.resolve(func.apply(this, args)).then(resolve);
|
||||
} else {
|
||||
calls.add({ args, resolve });
|
||||
}
|
||||
});
|
||||
},
|
||||
}[funcName],
|
||||
{
|
||||
cancel() {
|
||||
browser.cancelAnimationFrame(handle);
|
||||
calls.clear();
|
||||
handle = null;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------- HOOKS -----------------------------------
|
||||
|
||||
/**
|
||||
* Hook that returns a debounced version of the given function, and cancels
|
||||
* the potential pending execution on willUnmount.
|
||||
* @see debounce
|
||||
* @template {Function} T
|
||||
* @param {T} callback
|
||||
* @param {number | "animationFrame"} delay
|
||||
* @param {boolean} [immediate=false] whether the function should be called on
|
||||
* the leading edge instead of the trailing edge.
|
||||
* @returns {T & { cancel: () => void }}
|
||||
*/
|
||||
export function useDebounced(callback, delay, immediate = false) {
|
||||
const component = useComponent();
|
||||
const debounced = debounce(callback.bind(component), delay, immediate);
|
||||
onWillUnmount(() => debounced.cancel());
|
||||
return debounced;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user