有一个使用普通去抖动函数(Vue组件)的处理程序的搜索输入:
created() {
this.handleChange = debounce(async (ev) => {
this.loading = true;
const { target: { value: search } } = ev;
if (search) {
const response = await searchRepos({ search });
const repos = await response.json(response);
console.log(search);
console.log(repos?.items);
this.repos = repos?.items;
} else {
this.repos = [];
}
this.loading = false;
}, 500);
}
去抖动
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback.apply(null, args);
}, wait);
};
}
工作正常,但这里有一个时刻。回调并不等待对方,它可能会创建一个情况,当前一个回调返回值后,下一个回调。
例如,当用户擦除倒数第二个符号时发送请求,在此用户擦除最后一个符号时,其回调结束得更快,因为没有请求。然后前一个回调返回值,并显示无效信息。坚韧发送请求,也不能保证我们在前一个之后收到响应。
我的解决方案是像这样改进去抖动:
export const debounce = (callback, waitTime) => {
let timeoutId = null;
let isPreviousPerforming = false;
let callbacksOrder = [];
const performRest = async () => {
for (const order of callbacksOrder) {
await callback.apply(null, [order.ev]);
}
callbacksOrder = []
};
return (ev) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(async () => {
if (isPreviousPerforming) {
callbacksOrder.push({ ev });
return;
}
isPreviousPerforming = true;
await callback.apply(null, [ev]);
await performRest();
isPreviousPerforming = false;
}, waitTime);
};
}
但这里又是一个时刻:在for
和callbacksOrder = []
之间,我们可能会收到一个事件,这个事件将被推送到callbacksOrder,我们将删除它。
问题:以这种方式处理搜索输入有什么可能的解决方案或最佳实践?
P.S. v-debounce的工作原理与普通debounce类似。
回调应连续解决。
1条答案
按热度按时间l3zydbqr1#
如果你不需要结果,我不会等待所有的请求。相反,你可以在启动一个新的请求时用AbortController中止运行请求,这会拒绝所有当前的等待。但是你必须在你的
searchRepos()
中构建这个。类似这样的东西应该可以工作:
然后你可以将信号传递给
searchRepos()
:你在
searchRepos()
中对signal
做什么取决于你如何发送请求,但我认为现在AbortController
在任何地方都受到支持。