Подтвердить что ты не робот

Являются ли равные тайм-ауты, выполненные в Javascript?

Предположим, что я

setTimeout(foo, 0);

...

setTimeout(bar, 0);

Могу ли я быть уверенным, что foo начнет выполнение перед баром? Что, если вместо 0 я использую тайм-аут 1, 10 или 100 для бара?

Простые эксперименты показывают, что в случае равных значений таймаута цели таймаута выполняются в том же порядке, что и сами setTimeouts, но можно ли полагаться на это поведение?

4b9b3361

Ответ 1

Небезопасно полагаться на это поведение. Я написал тест script, в котором расписано несколько функций (и они, в свою очередь, также планируют ряд функций), все с использованием setTimeout (..., 0) и порядок, в котором вызывались функции, не был всегда совпадает с порядком, в котором setTimeout был вызван (по крайней мере, в Chrome 11, который я использовал для запуска script).

Вы можете увидеть/запустить script здесь: http://jsfiddle.net/se9Jn/ (script использует YUI для кросс-браузерной совместимости, но Y.later использует setTimeout внутри).

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

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

setTimeout(foo, 0);

...

function foo() {

    ...

    setTimeout(bar, 0);
}

Ответ 2

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

В частности, если в заданном контексте выполнения вы устанавливаете тайм-аут для n, а затем один для m, где n <= m, цели будут выполняться в том порядке, в котором установлены таймауты.

Но не верьте мне на слово. Я считаю, что реализация окна находится в nsGlobalWindow.cpp, и метод, который фактически решает, где тайм-ауты идут в очереди выполнения, называется InsertTimeoutIntoList. Похоже, что метод пересекает очередь назад, ища первый тайм-аут, который меньше или равен заданному тайм-ауту, и вставляет указанный таймаут после него.

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

Ответ 3

Короче говоря, не рассчитывайте на это. Посмотрите это.

Там много информации в этом цифра для переваривания, но понимание этого полностью даст вам лучшее реализация асинхронного Выполнение JavaScript выполняется.

Ответ 4

Ответ: Нет, порядок выполнения не гарантируется. Я иногда видел не-FIFO-заказ в chrome 40, особенно если я приостанавливаюсь в отладчике, пока ожидания не ожидаются. У меня также было редкое зрелище в дикой природе - это было единственное правдоподобное объяснение инцидента, который я исследовал.

Если вам нужен гарантированный порядок выполнения, вместо setTimeout(callback, 0) вы можете сделать это:

var queue = [];
function handleQueue() {
    queue.shift()();
}
function queueCallback(callback) {
   queue.push(callback);
   setTimeout(handleQueue, 0);
}

Теперь, для гарантированного foo, bar заказа вы можете:

queueCallback(foo);
...
queueCallback(bar);

Ответ 5

Существует определенный минимум, который может задержать на самом деле, и это сильно зависит от ОС, браузера, активности браузера и загрузки компьютера. Я, как правило, не опускаюсь ниже 20 мс, поскольку я думаю, что что-то меньшее, чем это, не имеет никакого значения.

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

Если вы хотите, чтобы это было сделано, чтобы я сделал что-то вроде этого:

setTimeout(function() { 
  foo();
  setTimeout(bar, 20)
}, 20);

Это всегда гарантирует порядок.

Если вы используете Firefox, чтобы убедиться, что ваш javascript на самом деле многопоточен, вы можете посмотреть на WebWorker, который поддерживается в новых браузерах, но не в IE.