setTimeout(): voidПри написании JavaScript-кода вам может понадобиться отложить выполнение функции.
Этим занимается setTimeout. Вы указываете функцию-колбэк, которую нужно выполнить позже, и значение, выражающее, насколько позже её запустить, в миллисекундах:
setTimeout(() => {
// выполнится через 2 секунды
}, 2000);
setTimeout(() => {
// выполнится через 50 миллисекунд
}, 50);Этот синтаксис определяет новую функцию. Внутри неё можно вызвать любую другую функцию либо передать имя существующей функции и набор параметров:
const myFunction = (firstParam, secondParam) => {
// делаем что-то
};
// выполнится через 2 секунды
setTimeout(myFunction, 2000, firstParam, secondParam);setTimeout возвращает экземпляр Timeout в Node.js, тогда как в браузерах он возвращает числовой ID таймера. Этот объект или ID можно использовать, чтобы отменить запланированное выполнение функции:
const timeout = setTimeout(() => {
// должно выполниться через 2 секунды
}, 2000);
// я передумал
clearTimeout(timeout);Если задать задержку таймаута равной 0, функция-колбэк выполнится как можно скорее, но после выполнения текущей функции:
setTimeout(() => {
console.log('after ');
}, 0);
console.log(' before ');Этот код напечатает
before
afterЭто особенно полезно, чтобы не блокировать CPU на интенсивных задачах и дать другим функциям выполниться во время тяжёлого вычисления, ставя функции в очередь планировщика.
Некоторые браузеры (IE и Edge) реализуют метод
setImmediate()с ровно такой же функциональностью, но он нестандартен и недоступен в других браузерах. При этом в Node.js это стандартная функция.
setInterval(): voidsetInterval — функция, похожая на setTimeout, с одним отличием: вместо однократного запуска колбэка она будет запускать его бесконечно, через указанный вами интервал времени (в миллисекундах):
setInterval(() => {
// выполняется каждые 2 секунды
}, 2000);Функция выше выполняется каждые 2 секунды, пока вы не скажете ей остановиться, используя clearInterval и передав ему id интервала, который вернул setInterval:
const timeout = setInterval(() => {
// выполняется каждые 2 секунды
}, 2000);
clearInterval(timeout);Часто clearInterval вызывают внутри колбэка setInterval, чтобы тот сам решал, стоит ли ему выполниться снова или остановиться. Например, этот код что-то выполняет, пока App.somethingIWait не примет значение arrived:
const interval = setInterval(() => {
if (App.somethingIWait === 'arrived') {
clearInterval(interval);
}
// иначе делаем что-то
}, 100);setInterval запускает функцию каждые n миллисекунд, не учитывая, когда функция завершила своё выполнение.
Если функция всегда занимает одно и то же время, всё хорошо:
0 1000 2000 3000
| | | |
| | | |
| [██████████] | |
| [exe script] | |
| [██████████] | |
| | [██████████] |
| | [exe script] |
| | [██████████] |
| | | [██████████]
| | | [exe script]
| | | [██████████]
|__________|___________|___________|____
Возможно, функция занимает разное время выполнения, например в зависимости от условий сети:
0 1000 2000 3000
| | | |
| | | |
| [██████████] | |
| [exe script] | |
| [██████████] | |
| | [████████████████████]
| | [ execute script ]
| | [████████████████████]
| | | [██████████]
| | | [exe script]
| | | [██████████]
|__________|___________|___________|____
А может быть, одно длинное выполнение накладывается на следующее:
0 1000 2000 3000 4000
| | | | |
| [████████████████████] | |
| [ execute script ] | |
| [████████████████████] | |
| [███████████████████████████] |
| [ execute script ] |
| [███████████████████████████] |
| | | [██████████████]
| | | [execute script]
| | | [██████████████]
|__________|___________|___________|___________|__
Чтобы этого избежать, можно запланировать рекурсивный setTimeout, вызываемый по завершении функции-колбэка:
const myFunction = () => {
// делаем что-то
setTimeout(myFunction, 1000);
};
setTimeout(myFunction, 1000);чтобы получить такой сценарий:
0 1000 2000 3000
| | | |
| [█████████████] | [█████████████]
| [ exec script ]>──1s──<[ exec script ]
| [█████████████] | [█████████████]
| | | |
|__________|____________|___________|__________
setTimeout и setInterval доступны в Node.js через модуль Timers.
Node.js также предоставляет setImmediate(), который планирует выполнение колбэка в фазе check event loop. В отличие от setTimeout(() => {}, 0), в общем случае это не эквивалентно, потому что их колбэки выполняются в разных фазах event loop, и порядок их выполнения зависит от контекста выполнения.