Introdução
Neste laboratório, exploraremos como criar uma função debounced (com debounce) que retorna uma promise em JavaScript. Aprenderemos como atrasar a invocação de uma função até que um tempo especificado tenha decorrido e como lidar com múltiplas promises retornadas durante esse tempo para garantir que todas retornem os mesmos dados. Ao final deste laboratório, você terá uma sólida compreensão de como implementar debouncing com promises em seus projetos JavaScript.
Debounce Promise (Promise com Debounce)
Para criar uma função debounced (com debounce) que retorna uma promise, atrasando a invocação da função fornecida até que pelo menos ms milissegundos tenham decorrido desde a última vez que foi invocada, use as seguintes etapas:
- Toda vez que a função debounced é invocada, limpe o timeout pendente atual com
clearTimeout(), então usesetTimeout()para criar um novo timeout que atrasa a invocação da função até que pelo menosmsmilissegundos tenham decorrido. - Use
Function.prototype.apply()para aplicar o contextothisà função e fornecer os argumentos necessários. - Crie uma nova
Promisee adicione seus callbacksresolveerejectà pilha de promisespending. - Quando
setTimeout()é chamado, copie a pilha atual (pois ela pode mudar entre a chamada da função fornecida e sua resolução), limpe-a e chame a função fornecida. - Quando a função fornecida resolve/rejeita, resolva/rejeite todas as promises na pilha (copiada quando a função foi chamada) com os dados retornados.
- Omita o segundo argumento,
ms, para definir o timeout em um padrão de0ms.
Aqui está o código para a função 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 });
});
};
Aqui está um exemplo de como 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);
// Will log ['resolved', 'bar'] both times
Resumo
Parabéns! Você concluiu o laboratório Debounce Promise. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.