Довольно часто см. в JavaScript-библиотеке код следующим образом:
setTimeout(function() {
...
}, 0);
Я хотел бы знать, зачем использовать такой код оболочки.
Довольно часто см. в JavaScript-библиотеке код следующим образом:
setTimeout(function() {
...
}, 0);
Я хотел бы знать, зачем использовать такой код оболочки.
Очень упрощено:
Браузеры однопоточные, и этот единственный поток (поток пользовательского интерфейса) распределяется между механизмом рендеринга и движком js.
Если вещь, которую вы хотите сделать, занимает много времени (мы говорим о циклах здесь, но все же), она может остановить (paus) рендеринг (поток и краска).
В браузерах также существует "Ведро", где все события сначала задерживаются, когда поток пользовательского интерфейса выполняется с тем, что он делает. Как только поток выполняется, он смотрит в ведро и сначала берет задачу.
Используя setTimeout
, вы создаете новую задачу в корзине после задержки и позволяете потоку справляться с ней, как только она доступна для большей работы.
История:
После задержки 0 мс создать новую задачу функции и положите его в ведро. В этот момент поток пользовательского интерфейса занят делать что-то еще, и есть еще одна задача в ковше уже. После 6ms поток доступен и получает задачу infront твой, хорошо, ты следующий. Но что? Это была одна огромная вещь! В нем есть был как foreeeeeever (30 мс)!
Наконец, теперь поток выполняется с этим и приходит и получает ваш Задача.
Большинство браузеров имеют минимальную задержку, которая больше 0, поэтому установка 0 в качестве задержки означает: Поместите эту задачу в корзину как можно скорее. Но говорить UA, чтобы поместить его в ведро ASAP, не является гарантией того, что он выполнит в тот момент. Ведро похоже на почтовое отделение, может быть, есть еще одна очередь других задач. Почтовые ветки также однопоточные, и только один человек помогает в решении всех задач... извините клиентов за свои задачи. Ваша задача должна попасть в очередь, как и все остальные.
Если браузер не использует собственный тикер, он использует циклы тиков ОС. У старых браузеров были минимальные задержки между 10-15 мс. HTML5 указывает, что если время задержки меньше 4 мс, UA должен увеличить его до 4 мс. Это называется согласованный в браузерах, выпущенных в 2010 году и далее.
Подробнее см. Как работает JavaScript Timers от Джона Ресига.
Изменить: Также см. Какая черта в цикле событий? Филипп Робертс из JSConf EU 2014 Это обязательный просмотр для всех людей, затрагивающих внешний код.
Есть несколько причин, почему вы это сделаете
setTimeout
или setInterval
для запускаПомимо предыдущих ответов я хотел бы добавить еще один полезный сценарий, о котором я могу думать: "побег" из блока try-catch. Задержка setTimeout изнутри блока try-catch будет выполняться вне блока, и любое исключение будет распространяться в глобальной области.
Возможно, лучший пример сценария: на сегодняшний день JavaScript с более распространенным использованием так называемых Deferreds/Promises для асинхронных обратных вызовов, которые вы часто выполняете внутри try-catch. Отложенные /Promises завершают обратный вызов в try-catch, чтобы иметь возможность обнаруживать и распространять исключение как ошибку в асинхронной цепочке. Все это хорошо для функций, которые должны быть в цепочке, но рано или поздно вы будете "сделаны" (т.е. выбрали все свои ajax) и хотите запустить простой неасинхронный код, где вы не хотите, чтобы исключения были "скрытый". AFAIK Dojo, Kris Kowal Q, MochiKit и Google Closure lib используют упаковку try-catch (но не jQuery).
(В несколько нечетных случаев я также использовал технику для перезапуска кода в одноэлементном стиле, не вызывая рекурсии. Я делаю перезапуск-перезапуск в том же цикле).
Если вы хотите выполнить остальную часть своего кода, не дожидаясь предыдущего, вы должны добавить его в анонимный метод, переданный функции setTimeout. В противном случае ваш код будет ждать, пока не будет выполнено предыдущее
Пример:
function callMe()
{
for(var i = 0; i < 100000; i++)
{
document.title = i;
}
}
var x = 10;
setTimeout(callMe, 0);
var el = document.getElementById('test-id');
el.innerHTML = 'Im done before callMe method';
Вот почему я использую его.
Чтобы разрешить выполнение любых ранее заданных тайм-аутов.