简介
在本实验中,我们将探索如何在 JavaScript 中创建一个返回 Promise 的防抖函数。我们将学习如何延迟调用一个函数,直到指定的时间过去,以及如何处理在此期间返回的多个 Promise,以确保它们都返回相同的数据。在本实验结束时,你将对如何在 JavaScript 项目中使用 Promise 实现防抖有深入的理解。
这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 100%。获得了学习者 100% 的好评率。
防抖 Promise
要创建一个返回 Promise 的防抖函数,该函数会延迟调用提供的函数,直到自上次调用以来至少经过了 ms 毫秒,请按以下步骤操作:
- 每次调用防抖函数时,使用
clearTimeout()清除当前挂起的超时,然后使用setTimeout()创建一个新的超时,该超时会延迟调用函数,直到至少经过了ms毫秒。 - 使用
Function.prototype.apply()将this上下文应用于函数并提供必要的参数。 - 创建一个新的
Promise,并将其resolve和reject回调添加到挂起的 Promise 堆栈中。 - 当调用
setTimeout()时,复制当前堆栈(因为在提供的函数调用与其解析之间它可能会改变),清除它并调用提供的函数。 - 当提供的函数解析/拒绝时,使用返回的数据解析/拒绝堆栈中的所有 Promise(在调用函数时复制)。
- 省略第二个参数
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']
总结
恭喜你!你已经完成了防抖 Promise 实验。你可以在 LabEx 中练习更多实验来提升你的技能。