В javascript нет разделения по времени. Javascript является однопоточным (за исключением веб-воркеров, которые мы здесь не обсуждаем). Один поток выполнения javascript выполняется до его завершения.
В вашем первом примере кода анимация делает свое дело, и когда она полностью завершена, она вызывает ваш my_cpu_heavy_function
.
Во втором примере кода анимация инициализируется и устанавливает таймер для первого шага анимации. Затем он возвращается и переходит к следующей строке кода. Анимация только началась (и поставить таймер на короткое время, чтобы в будущем сделать еще какую-то работу) - она еще не завершена. Затем запускается ваш my_cpu_heavy_function
, и он выполняет все выполнение javascript до тех пор, пока оно не будет выполнено. Анимация вообще не запускается, пока работает my_cpu_heavy_function
. Когда он завершится, сработает событие таймера, указывающее на то, что набор анимации запущен, и анимация продолжит работу.
Анимации могут «выглядеть» как разрезание времени, но на самом деле это не так. Анимации jQuery перемещаются на один шаг в анимации, а затем устанавливают таймер на некоторое небольшое время в будущем, и они возвращаются обратно в систему. Когда это событие таймера срабатывает, jQuery выполняет следующий шаг в анимации и так далее. Когда срабатывает событие таймера, оно помещает событие таймера в очередь событий javascript. Если в данный момент не запущен javascript, обратный вызов таймера запускается немедленно. Если в данный момент выполняется javascript, то событие таймера просто находится в очереди событий до тех пор, пока не завершится текущий поток javascript. Когда этот поток завершается, javascript просматривает очередь событий, чтобы увидеть, есть ли какие-либо ожидающие события. Если есть, то он вызывает обратный вызов события.
Таким образом, на самом деле нет разделения времени на разные части javascript. Два фрагмента кода, которые хотят запустить, не получают каждый цикл ЦП, как это происходит с реальными потоками в нативном коде. В javascript один фрагмент кода выполняется до тех пор, пока он не будет выполнен, а затем может быть запущено следующее событие. В таких вещах, как анимация на основе javascript, разделение времени можно в некоторой степени смоделировать, выполнив небольшой объем работы, а затем установив таймер на какое-то время в будущем и вернувшись в систему. Как только вы закончите выполнение, может запуститься какой-то другой фрагмент javascript, но он также будет работать до тех пор, пока не будет выполнен. Если все фрагменты javascript выполняют только крошечные объемы работы, а затем устанавливают таймер для следующего фрагмента работы, тогда все они могут сотрудничать, и это будет выглядеть так, как будто существует разделение времени, но это работает только из-за сотрудничества между ними всеми. Если появляется одна функция, такая как my_cpu_heavy_function
, и на какое-то время загружает ЦП, в это время больше никто не запускается. Анимация останавливалась во время работы my_cpu_heavy_function
.
Некоторые операции в браузере выполняются собственным кодом в браузере (например, вызовы ajax, загрузка изображений и т. д.). Эти асинхронные задачи могут выполняться в фоновом режиме во время выполнения javascript, но они не будут уведомлять javascript до тех пор, пока не завершится текущий поток выполнения javascript и не будет запущен новый поток с обратным вызовом уведомления.
В качестве примера предположим, что у нас есть изображение, загрузка которого занимает 1 секунду, и функция с интенсивным использованием ЦП, выполнение которой занимает 5 секунд. Затем у нас есть этот код:
var img = new Image();
img.onload = function() {
alert("image is loaded now");
}
img.src = "xxx.jpg";
longFunctionThatTakesFiveSecondsToRun();
Когда мы запускаем этот код, несмотря на то, что изображение загружается внутри браузера всего за 1 секунду, обработчик onload не будет вызываться до тех пор, пока longFunctionThatTakesFiveSecondsToRun()
не завершится через 5 секунд. Он должен дождаться завершения текущего потока выполнения, прежде чем можно будет обработать событие onload.
Если вы хотите узнать больше об очередях событий javascript и асинхронных операциях, см. следующие связанные ответы:
Как JavaScript обрабатывает ответы AJAX в фоновом режиме?
Условия гонки с обработкой событий JavaScript?
Могут ли обработчики событий JS прерывать выполнение другого обработчика?
Нужно ли мне быть обеспокоены условиями гонки с асинхронным Javascript?
person
jfriend00
schedule
08.09.2012