Случайное поведение setTimeout на консоли.Как рассчитать порядок и причину такого поведения? - PullRequest
0 голосов
/ 25 июня 2018
for (var i = 0; i < 5; i++) {
  function timer(j) {
    setTimeout(function() {
      alert(j);
    }, 1000);
  }
  timer(i);
};

Этот код генерирует случайные результаты подсчета. Почему такое поведение и что я могу сделать, чтобы получить правильные упорядоченные подсчеты.

Ответы [ 3 ]

0 голосов
/ 25 июня 2018

Когда скрипт выполняется, цикл for работает, и вы инициализируете 5 setTimeout с одновременно, каждый из которых истекает через 1000 миллисекунд. Поскольку все они настроены на одновременную работу, а setTimeout не имеет даже миллисекунды, порядок тайм-аута не будет предсказуемым. Другой потенциальный фактор, вызывающий смущение, заключается в том, что alert блоков .

Как показывают приведенные ниже комментарии, setTimeout s может работать в том порядке, в котором они были установлены, но это не гарантировано - поведение может отличаться в разных браузерах. Итак, если вы хотите убедиться, что они работают в том порядке, в котором они были установлены, добавьте несколько миллисекунд для каждой итерации:

for (var i = 0; i < 5; i++) {
  function timer(j) {
    setTimeout(function() {
      console.log(j);
    }, 1000 + (j * 12));
  }
  timer(i);
}

alert версия:

for (var i = 0; i < 5; i++) {
  function timer(j) {
    setTimeout(function() {
      alert(j);
    }, 1000 + (j * 12));
  }
  timer(i);
}
0 голосов
/ 25 июня 2018

Случайное поведение setTimeout на консоли, ... и причина этого поведения?

Как уже упоминалось, порядок выполнения для каждого setTimeout не гарантируется, и чтопотому что они работают независимо друг от друга, основываясь на заданной задержке, а не в их начальном порядке, и поэтому могут стрелять случайным образом.

Как получить счет в порядке ...?

Опять же, как уже упоминалось, незначительное изменение в задержке может быть одним из решений, тем не менее, это также не гарантируется по той же причине, хотя при достаточно большой разнице в задержке это, скорее всего, будет.


Предполагая, что вы хотите запустить некоторое количество функций с задержкой и в определенном «гарантированном» порядке, здесь есть одно решение, где вы сохраняете функции в массиве, а затем выполняете их1 на 1.

Фрагмент стека - с предупреждением

var fn_arr = [];

for (let i = 0; i < 5; i++) {
  fn_arr.push( function() { alert(i) } )  
};

setTimeout(function() {
  fn_arr.forEach( (fn) => fn() )
}, 1000);

Фрагмент стека - с консолью

var fn_arr = [];

for (let i = 0; i < 5; i++) {
  fn_arr.push( function() { console.log(i) } )  
};

setTimeout(function() {
  fn_arr.forEach( (fn) => fn() )
}, 1000);
0 голосов
/ 25 июня 2018

Вы запускаете пять таймеров, в очень быстрой последовательности и все с одинаковой задержкой.Я подозреваю, что если бы вы посмотрели на внутренние детали того, когда таймеры предназначены для срабатывания, у всех них было бы одинаковое целевое время, если системные часы не «тикают» между экземплярами таймера.

Естьнет строгого порядка таймеров, которые должны срабатывать эффективно одновременно.Все, что вы видите, - это несколько таймеров, запускаемых примерно в одно и то же время, без какого-либо определенного порядка.Это похоже на одновременное срабатывание 5 фейерверков, каждый с одинаковой длиной предохранителя - все они сработают примерно в одно и то же время, но нет гарантии, что тот, который вы зажгли первым, зажжет первым.Это просто природа таймеров, и лучше с этим не бороться.

Если вы хотите сделать много вещей одновременно в будущем, я предлагаю вам запустить один таймер, который выполняет всетребуемые операции при его запуске.

Если вам действительно действительно нужно дополнительное упорядочение, но для того, чтобы все запускалось «в основном в одно и то же время», вы могли бы заставить каждый таймер сохранять ссылку на «предыдущий» таймер и ждатьдля этого таймера, чтобы закончить первым.Это было бы довольно уродливо, и я бы по крайней мере попытался избежать этого.Либо события должны быть независимыми, в этом случае порядок не имеет значения, либо они взаимозависимы, и в этом случае вы, вероятно, должны планировать их по-другому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...