Introducción
En este laboratorio, exploraremos cómo crear una función anti-rebote que devuelva una promesa en JavaScript. Aprenderemos cómo retrasar la invocación de una función hasta que haya transcurrido un tiempo especificado, y cómo manejar múltiples promesas devueltas durante este tiempo para garantizar que todas devuelvan los mismos datos. Al final de este laboratorio, tendrás una comprensión sólida de cómo implementar el anti-rebote con promesas en tus proyectos de JavaScript.
Promesa anti-rebote
Para crear una función anti-rebote que devuelva una promesa, retrasando la invocación de la función proporcionada hasta que hayan transcurrido al menos ms milisegundos desde la última vez que se invocó, siga los siguientes pasos:
- Cada vez que se invoque la función anti-rebote, quite el temporizador pendiente actual con
clearTimeout(), luego usesetTimeout()para crear un nuevo temporizador que retrasará la invocación de la función hasta que hayan transcurrido al menosmsmilisegundos. - Use
Function.prototype.apply()para aplicar el contextothisa la función y proporcionar los argumentos necesarios. - Cree una nueva
Promisey agregue sus devoluciones de llamadaresolveyrejecta la pila de promesas pendientes. - Cuando se llame a
setTimeout(), copie la pila actual (ya que puede cambiar entre la llamada a la función proporcionada y su resolución), límpiela y llame a la función proporcionada. - Cuando la función proporcionada se resuelva/rechace, resuelva/rechace todas las promesas en la pila (copiada cuando se llamó a la función) con los datos devueltos.
- Omita el segundo argumento,
ms, para establecer el temporizador con un valor predeterminado de0ms.
A continuación, se muestra el código de la función debouncePromise():
const debouncePromise = (fn, ms = 0) => {
let timeoutId;
const pending = [];
return (...args) =>
new Promise((res, rej) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
const currentPending = [...pending];
pending.length = 0;
Promise.resolve(fn.apply(this, args)).then(
(data) => {
currentPending.forEach(({ resolve }) => resolve(data));
},
(error) => {
currentPending.forEach(({ reject }) => reject(error));
}
);
}, ms);
pending.push({ resolve: res, reject: rej });
});
};
A continuación, se muestra un ejemplo de cómo usar debouncePromise():
const fn = (arg) =>
new Promise((resolve) => {
setTimeout(resolve, 1000, ["resolved", arg]);
});
const debounced = debouncePromise(fn, 200);
debounced("foo").then(console.log);
debounced("bar").then(console.log);
// Ambos veces mostrará ['resolved', 'bar']
Resumen
¡Felicitaciones! Has completado el laboratorio de Promesa anti-rebote. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.