Введение
В этом практическом занятии мы изучим, как создать функцию, которая возвращает промис в JavaScript и имеет защиту от "дребезга". Мы узнаем, как откладывать вызов функции до истечения определенного времени и как обрабатывать несколько возвращаемых промисов в это время, чтобы гарантировать, что они все возвращают одинаковые данные. В конце этого практического занятия вы глубоко поймете, как реализовать защиту от "дребезга" с использованием промисов в своих проектах на JavaScript.
Debounce Promise
Чтобы создать функцию, которая возвращает промис и имеет защиту от "дребезга", задерживая вызов предоставленной функции до тех пор, пока не пройдет как минимум ms миллисекунд с момента последнего вызова, используйте следующие шаги:
- Каждый раз, когда функция с защитой от "дребезга" вызывается, отмените текущий отложенный таймаут с помощью
clearTimeout(), а затем используйтеsetTimeout(), чтобы создать новый таймаут, который задерживает вызов функции до тех пор, пока не пройдет как минимумmsмиллисекунд. - Используйте
Function.prototype.apply(), чтобы применить контекстthisк функции и передать необходимые аргументы. - Создайте новый
Promiseи добавьте егоresolveиrejectколлбэки в стек ожидающих промисов. - Когда вызывается
setTimeout(), скопируйте текущий стек (так как он может измениться между вызовом предоставленной функции и ее разрешением), очистите его и вызовите предоставленную функцию. - Когда предоставленная функция разрешается/отклоняется, разрешите/отклоните все промисы в стеке (скопированный при вызове функции) с возвращенными данными.
- Игнорируйте второй аргумент,
ms, чтобы установить таймаут по умолчанию в0мс.
Вот код для функции 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 });
});
};
Вот пример использования 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);
// В обоих случаях будет выведено ['resolved', 'bar']
Резюме
Поздравляем! Вы завершили практическое занятие по Debounce Promise. Вы можете выполнить больше практических занятий в LabEx, чтобы улучшить свои навыки.