在用户连续键入时每 500 毫秒执行一次功能不超过一次
Execute a function not more than once every 500 milliseconds while user types continuously
我正在尝试实现类似自动完成的功能,所以我在 运行 在 oninput 事件触发时启用该功能。因为我正在发出获取请求而不是 运行 在每次更改时都希望它 运行 它在(可能)500 毫秒内不超过一次。有办法吗?
<body>
<input id="input" type="text">
<script>
function filterData(substr) {
fetch(url)
.then(response => response.json())
.then(data => {
let filteredData = data.filter(person => person.name.includes(substr));
print(filteredData);
})
}
document.getElementById("input").oninput = (e) => filterData(e.target.value);
</script>
</body>
您好,为此使用此代码超时
var timeoutId
function autoComplete(substr)
{
// stop previous timeouts
clearTimeout(timeoutId)
timeoutId = setTimeout(function () {
fetch(url)
.then(response => response.json())
.then(data => {
let filteredData = data.filter(person =>
person.name.includes(substr));
print(filteredData);
})
});
}, 1000);
}
OP 的描述类似于节流行为。为了同时实现 throttled 进程及其兄弟 debounced 进程,有多种 libraries/implementations 可用。常用的有lodash and/or underscore.js.
的方法
下一个提供的示例代码使用了最初提供的 OP filterData
的模拟版本。它显示了 lodash 和两个 基本自定义 throttle
/debounce
实现的不同节流和去抖行为.. .
/*function filterData(substr) {
fetch(url)
.then(response => response.json())
.then(data => {
let filteredData = data.filter(person => person.name.includes(substr));
print(filteredData);
});
}*/
function filterData(substr) {
new Promise((resolve/*, reject*/) => {
setTimeout(() => {
resolve({
search: substr,
matches: [substr + 'Bar', substr + ' bazz', substr + ' Foooo']
});
}, 300);
}).then(response => console.log({ response }));
}
function handleSearch(evt) {
// console.log('this :', this);
// // return filterData(this.value);
return filterData(evt.target.value);
}
document
.querySelector("#basicThrottled")
.addEventListener('input', basicThrottle(handleSearch, 500));
document
.querySelector("#basicDebounced")
.addEventListener('input', basicDebounce(handleSearch, 500));
document
.querySelector("#lodashThrottled")
.addEventListener('input', _.throttle(handleSearch, 500));
document
.querySelector("#lodashDebounced")
.addEventListener('input', _.debounce(handleSearch, 500));
body { margin: 0; }
[type="search"] { min-width: 24%; max-width: 24%; }
.as-console-wrapper { min-height: 85%; }
<input id="basicThrottled" type="search" placeholder="basic throttled ..." />
<input id="basicDebounced" type="search" placeholder="basic debounced ..." />
<input id="lodashThrottled" type="search" placeholder="lodash throttled ..." />
<input id="lodashDebounced" type="search" placeholder="lodash debounced ..." />
<script>
function basicDebounce(proceed, delay = 300, target) {
let timeoutId = null;
return function debounced(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(proceed.bind(target ?? this), delay, ...args);
};
}
function basicThrottle(proceed, threshold = 200, target) {
let timeoutId = null;
let referenceTime = 0;
return function throttled(...args) {
const currentTime = Date.now();
if (currentTime - referenceTime >= threshold) {
clearTimeout(timeoutId);
referenceTime = currentTime;
const trigger = proceed.bind((target ?? this), ...args);
timeoutId = setTimeout((() => {
referenceTime = 0;
trigger();
}), threshold);
trigger();
}
};
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
我正在尝试实现类似自动完成的功能,所以我在 运行 在 oninput 事件触发时启用该功能。因为我正在发出获取请求而不是 运行 在每次更改时都希望它 运行 它在(可能)500 毫秒内不超过一次。有办法吗?
<body>
<input id="input" type="text">
<script>
function filterData(substr) {
fetch(url)
.then(response => response.json())
.then(data => {
let filteredData = data.filter(person => person.name.includes(substr));
print(filteredData);
})
}
document.getElementById("input").oninput = (e) => filterData(e.target.value);
</script>
</body>
您好,为此使用此代码超时
var timeoutId
function autoComplete(substr)
{
// stop previous timeouts
clearTimeout(timeoutId)
timeoutId = setTimeout(function () {
fetch(url)
.then(response => response.json())
.then(data => {
let filteredData = data.filter(person =>
person.name.includes(substr));
print(filteredData);
})
});
}, 1000);
}
OP 的描述类似于节流行为。为了同时实现 throttled 进程及其兄弟 debounced 进程,有多种 libraries/implementations 可用。常用的有lodash and/or underscore.js.
的方法下一个提供的示例代码使用了最初提供的 OP filterData
的模拟版本。它显示了 lodash 和两个 基本自定义 throttle
/debounce
实现的不同节流和去抖行为.. .
/*function filterData(substr) {
fetch(url)
.then(response => response.json())
.then(data => {
let filteredData = data.filter(person => person.name.includes(substr));
print(filteredData);
});
}*/
function filterData(substr) {
new Promise((resolve/*, reject*/) => {
setTimeout(() => {
resolve({
search: substr,
matches: [substr + 'Bar', substr + ' bazz', substr + ' Foooo']
});
}, 300);
}).then(response => console.log({ response }));
}
function handleSearch(evt) {
// console.log('this :', this);
// // return filterData(this.value);
return filterData(evt.target.value);
}
document
.querySelector("#basicThrottled")
.addEventListener('input', basicThrottle(handleSearch, 500));
document
.querySelector("#basicDebounced")
.addEventListener('input', basicDebounce(handleSearch, 500));
document
.querySelector("#lodashThrottled")
.addEventListener('input', _.throttle(handleSearch, 500));
document
.querySelector("#lodashDebounced")
.addEventListener('input', _.debounce(handleSearch, 500));
body { margin: 0; }
[type="search"] { min-width: 24%; max-width: 24%; }
.as-console-wrapper { min-height: 85%; }
<input id="basicThrottled" type="search" placeholder="basic throttled ..." />
<input id="basicDebounced" type="search" placeholder="basic debounced ..." />
<input id="lodashThrottled" type="search" placeholder="lodash throttled ..." />
<input id="lodashDebounced" type="search" placeholder="lodash debounced ..." />
<script>
function basicDebounce(proceed, delay = 300, target) {
let timeoutId = null;
return function debounced(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(proceed.bind(target ?? this), delay, ...args);
};
}
function basicThrottle(proceed, threshold = 200, target) {
let timeoutId = null;
let referenceTime = 0;
return function throttled(...args) {
const currentTime = Date.now();
if (currentTime - referenceTime >= threshold) {
clearTimeout(timeoutId);
referenceTime = currentTime;
const trigger = proceed.bind((target ?? this), ...args);
timeoutId = setTimeout((() => {
referenceTime = 0;
trigger();
}), threshold);
trigger();
}
};
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>