Просто наткнулся на комментарий в этот очень старый вопрос относительно очистки всех setTimeouts.
Комментарий заинтриговал меня, поскольку на самом деле он не затрагивает вопрос напрямую, но предлагает действительно интересное альтернативное решение проблемы отслеживания нескольких таймеров, но, к сожалению, он не предлагает примера того, как это можно реализовать:
Use a global timeout which all of your other functions derive timing from. This will make everything run faster, and be easier to manage, although it will add some abstraction to your code...
... I just meant that you have one global timeout running once every 50ms. Every other function which would require a timing element would then grab it from the global timeout. Google switched to this for efficiency, although I can no longer find the article quoting it.
Как можно установить то, что я предполагаю, является именованным таймером в глобальном пространстве, а затем ссылаться на него в другом месте во многих случаях?
Например, если бы у нас было что-то подобное в глобальном пространстве:
let myGlobalTimer = setTimeout(function(){ myFunc(); }, 50);
Это будет запускать myFunc каждые 50 мс.
Я почти уверен, что вы не можете передавать имена динамических функций в setTimeout, так как же этого добиться?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


У вас может быть тайм-аут, проходящий через массив или Set функций каждый раз, когда срабатывает тайм-аут. Чтобы добавить функцию, которая запускается на каждой итерации, добавьте ее в Set; чтобы остановить его работу, удалите его из Set. Например:
const fns = new Set();
function runAllTasks() {
for (const fn of fns) {
fn();
}
// Run every 500 ms:
setTimeout(runAllTasks, 500);
}
fns.add(() => console.info('fn one running'));
const fn2 = () => console.info('fn two running');
fns.add(fn2);
runAllTasks();
// example, remove fn2 from the Set after 1300ms:
setTimeout(() => {
fns.delete(fn2);
}, 1300);Конечно, вы также можете использовать массив, но Set более подходит, когда порядок элементов в коллекции не имеет значения.
Вау, это впечатляет! Таким образом, будет запущен только 1 setTimeout независимо от того, сколько функций вы добавите в Set?
Есть ли шанс, что вы могли бы использовать версию этого в ванильном JS вместо ES2015, пожалуйста? Я просто прогнал его через декомпилятор babel, и это выглядело безумно, лол. pastebin.com/5CZ5tUjN
Как это решение будет работать, если у функций разные таймауты? Например. функция 1 должна выполняться через 500 мс, а функция 2 должна выполняться через 1700 мс? Также он запускает одни и те же функции снова и снова, а не раз и навсегда? Также вы делаете второй тайм-аут для удаления функции из набора, который, похоже, противоречит ограничению вопроса, заключающемуся в использовании одного глобального тайм-аута.
@ kfedorov91 это не проблема для моего конкретного случая использования. Все таймеры, которые я использую для этого конкретного аспекта проекта, работают с интервалами 500 мс. Так что это решение идеально подходит для меня. Я предполагаю, что функцию удаления можно вызвать напрямую без тайм-аута, верно?
@spice Если вы не хотите использовать for..of, вы можете использовать вместо него forEach. fns.forEach(fn => fn())
@spice, если вам не нужны переменные тайм-ауты для каждого обратного вызова, почему бы тогда просто не использовать setInterval ()?
@ kfedorov91 в основном используется для обновления отображения времени (и сохранения времени) при воспроизведении звука. setTimeout для этого намного более последователен, чем setInterval.
@spice, этот ES2015 - это Vanilla JS
@ spice - только если вы устанавливаете задержку для каждого вызова setTimeout на основе времени, оставшегося до следующего тика 500 мс после завершения всех функций. Этот ответ установит задержку на 500 мс после завершения последней функции, что не даст задержек даже на 500 мс.
@ vol7ron Я имел в виду, что он использует ES6. Я пишу этот конкретный проект прямо на oldskool JS (без жирных стрелок), поэтому я не использую webpack или какой-либо другой компилятор. Я поставил себе задачу узнать больше о ванильном JS в этом проекте, я даже нигде не использую jQuery для этого. Хотел лучше узнать, что находится под капотом, поэтому выбрал многословный подход: D
Значит, вы все еще изучаете определенную версию JS. Сначала вам следует узнать, какую версию вы пытаетесь поддерживать. Каждая версия имеет свои заметные отличия, особенно в разных браузерах.
Чтение некоторых ответов и переход по некоторым ссылкам приводит к этому планировщику: Как избежать проблем с setTimeout и setInterval в JavaScript, который немного сложнее, чем ответ ниже (хотя он неправильно использует термин «контекст», когда он означает «это»).