Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Исправляет функцию debounce() #5493

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions js/debounce/demos/debounced-search/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,11 @@
const searchResults = document.querySelector('.search-results')

function debounce(callee, timeoutMs) {
return function perform(...args) {
let previousCall = this.lastCall
this.lastCall = Date.now()

if (previousCall && ((this.lastCall - previousCall) <= timeoutMs)) {
clearTimeout(this.lastCallTimer)
}

this.lastCallTimer = setTimeout(() => callee(...args), timeoutMs)
}
let timer;
return (...args) => {
TatianaFokina marked this conversation as resolved.
Show resolved Hide resolved
loonlylokly marked this conversation as resolved.
Show resolved Hide resolved
clearTimeout(timer);
timer = setTimeout(() => { callee.apply(this, args); }, timeoutMs);
};
}

function handleInput(e) {
Expand Down
24 changes: 13 additions & 11 deletions js/debounce/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,23 +233,25 @@ const server = {

Итак, `debounce()` — это функция высшего порядка, принимающая аргументом функцию, которую надо «отложить».

Поехали. Аргументами будут функция, которую надо «откладывать», и интервал времени, спустя который следует вызывать функцию. Как результат возвращаем другую функцию. Это нужно, чтобы мы могли не менять другие части кода. Чуть позже увидим, как это помогает. В переменной `previousCall` мы храним временную метку предыдущего вызова, а в переменной текущего вызова — временную метку нынешнего момента. Это нужно, чтобы потом сравнить, когда функция была вызвана в этот раз и в предыдущий. Если разница между вызовами меньше, чем указанный интервал, то мы очищаем таймаут, который отвечает за непосредственно вызов функции-аргумента. Обратите внимание, что мы передаём все аргументы `...args`, которые получаем в функции `perform()`. Это тоже нужно, чтобы не приходилось менять другие части кода. Если таймаут был очищен, вызова не произойдёт. Если он не был очищен, то вызовется `callee`. Таким образом, мы как бы «отодвигаем» вызов `callee` до тех пор, пока «снаружи всё не подуспокоится».
Поехали. Аргументами будут функция, которую надо «откладывать», и интервал времени, спустя который следует вызывать функцию. Как результат возвращаем другую функцию. Это нужно, чтобы мы могли не менять другие части кода. Чуть позже увидим, как это помогает.

Обратите внимание, что мы передаём все аргументы `...args`, которые получаем в возвращаемой стрелочной функции. Это тоже нужно, чтобы не приходилось менять другие части кода. Если таймаут был очищен, вызова не произойдёт. Если он не был очищен, то вызовется `callee`. Таким образом, мы как бы «отодвигаем» вызов `callee` до тех пор, пока «снаружи всё не подуспокоится».
TatianaFokina marked this conversation as resolved.
Show resolved Hide resolved

```javascript
function debounce(callee, timeoutMs) {
return function perform(...args) {
let previousCall = this.lastCall
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => { callee.apply(this, args); }, timeoutMs);
};
loonlylokly marked this conversation as resolved.
Show resolved Hide resolved
}
```

this.lastCall = Date.now()
Как работает стрелочная функция, которую возвращает `debounce`:
TatianaFokina marked this conversation as resolved.
Show resolved Hide resolved

if (previousCall && this.lastCall - previousCall <= timeoutMs) {
clearTimeout(this.lastCallTimer)
}
1. При вызове функции, возвращаемой debounce, сначала выполняется `clearTimeout(timer)`. Это удаляет ранее установленный таймер, если он существует. Это необходимо, чтобы предотвратить выполнение предыдущего вызова функции `callee`, если новый вызов произошел до завершения задержки.
loonlylokly marked this conversation as resolved.
Show resolved Hide resolved

this.lastCallTimer = setTimeout(() => callee(...args), timeoutMs)
}
}
```
1. Затем устанавливается новый таймер с помощью setTimeout, и ссылка на этот таймер сохраняется в переменной timer.
loonlylokly marked this conversation as resolved.
Show resolved Hide resolved

Использовать такой `debounce()` мы можем так:

Expand Down
Loading