Установка и использование одного глобального setTimeout?

Просто наткнулся на комментарий в этот очень старый вопрос относительно очистки всех 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, так как же этого добиться?

Чтение некоторых ответов и переход по некоторым ссылкам приводит к этому планировщику: Как избежать проблем с setTimeout и setInterval в JavaScript, который немного сложнее, чем ответ ниже (хотя он неправильно использует термин «контекст», когда он означает «это»).

RobG 01.10.2018 05:01
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У вас может быть тайм-аут, проходящий через массив или 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?

spice 01.10.2018 04:04

Есть ли шанс, что вы могли бы использовать версию этого в ванильном JS вместо ES2015, пожалуйста? Я просто прогнал его через декомпилятор babel, и это выглядело безумно, лол. pastebin.com/5CZ5tUjN

spice 01.10.2018 04:08

Как это решение будет работать, если у функций разные таймауты? Например. функция 1 должна выполняться через 500 мс, а функция 2 должна выполняться через 1700 мс? Также он запускает одни и те же функции снова и снова, а не раз и навсегда? Также вы делаете второй тайм-аут для удаления функции из набора, который, похоже, противоречит ограничению вопроса, заключающемуся в использовании одного глобального тайм-аута.

pretzelhammer 01.10.2018 04:10

@ kfedorov91 это не проблема для моего конкретного случая использования. Все таймеры, которые я использую для этого конкретного аспекта проекта, работают с интервалами 500 мс. Так что это решение идеально подходит для меня. Я предполагаю, что функцию удаления можно вызвать напрямую без тайм-аута, верно?

spice 01.10.2018 04:11

@spice Если вы не хотите использовать for..of, вы можете использовать вместо него forEach. fns.forEach(fn => fn())

CertainPerformance 01.10.2018 04:14

@spice, если вам не нужны переменные тайм-ауты для каждого обратного вызова, почему бы тогда просто не использовать setInterval ()?

pretzelhammer 01.10.2018 04:17

@ kfedorov91 в основном используется для обновления отображения времени (и сохранения времени) при воспроизведении звука. setTimeout для этого намного более последователен, чем setInterval.

spice 01.10.2018 04:20

@spice, этот ES2015 - это Vanilla JS

vol7ron 01.10.2018 04:51

@ spice - только если вы устанавливаете задержку для каждого вызова setTimeout на основе времени, оставшегося до следующего тика 500 мс после завершения всех функций. Этот ответ установит задержку на 500 мс после завершения последней функции, что не даст задержек даже на 500 мс.

RobG 01.10.2018 04:53

@ vol7ron Я имел в виду, что он использует ES6. Я пишу этот конкретный проект прямо на oldskool JS (без жирных стрелок), поэтому я не использую webpack или какой-либо другой компилятор. Я поставил себе задачу узнать больше о ванильном JS в этом проекте, я даже нигде не использую jQuery для этого. Хотел лучше узнать, что находится под капотом, поэтому выбрал многословный подход: D

spice 01.10.2018 07:12

Значит, вы все еще изучаете определенную версию JS. Сначала вам следует узнать, какую версию вы пытаетесь поддерживать. Каждая версия имеет свои заметные отличия, особенно в разных браузерах.

vol7ron 01.10.2018 12:50

Другие вопросы по теме