Как происходит разделение времени в javascript?

или ecmascript, но мне интересно, зависит ли то, как это происходит на самом деле, больше от точной реализации.

JavaScript технически однопоточный.

но если я сделаю что-то вроде

$myDIv.animate({
    height:"100px"
});

какая разница, если я сделаю

A.

$myDIv.animate({
    height:"100px"
}, null, my_cpu_heavy_function);

or B.

$myDIv.animate({
    height:"100px"
});
my_cpu_heavy_function();

потому что во втором анимация будет бороться за время обработки с тяжелой функцией процессора, и поэтому внешний вид анимации пострадает, верно?

Итак, прекращает ли Javascript выполнение в конце синхронного блока кода или он обрезает один блок в любой случайной точке, чтобы разрешить обработку другого блока, работающего асинхронно?


person dolphone bubleine    schedule 08.09.2012    source источник


Ответы (2)


какая разница, если я делаю А или Б

Да, это будет иметь значение.

Вторая версия не так сильно борется за время обработки. Это больше похоже на то, что my_cpu_heavy_function будет занимать все время обработки после его начала, если оно синхронно.

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

Итак, что произойдет, так это то, что анимация начнется и выполнит свою инициализацию, но затем немедленно запустится my_cpu_heavy_function и заблокирует остальную часть анимации до ее завершения.

person gray state is coming    schedule 08.09.2012
comment
Асинхронные вещи все еще могут происходить (например, загрузка удаленных ресурсов), хотя это не относится к animate — просто события/обратные вызовы будут отложены до тех пор, пока на странице не перестанет выполняться другой код. - person ; 08.09.2012
comment
@pst: обратный вызов — это просто еще один фрагмент асинхронного кода, который запускается после окончательного асинхронного кода анимации. Весь асинхронный код блокируется, пока выполняется некоторый синхронный код. Код синхронизации не позволит выполнить асинхронность до тех пор, пока она не будет завершена. - person gray state is coming; 08.09.2012
comment
Что касается вашего обновленного комментария, да (загрузка удаленных ресурсов), но это вне среды выполнения JavaScript. - person gray state is coming; 08.09.2012
comment
Обратные вызовы @graystateiscoming выполняются синхронно; это [собственная] операция (например, AJAX), которая может работать асинхронно. - person ; 08.09.2012
comment
@pst: обратный вызов будет выполняться асинхронно по отношению к коду инициализации. То, как он вызывается по отношению к внутренней работе .animate, зависит от реализации. Его вызов будет либо синхронным с последним синхронизированным обновлением, либо асинхронным после последнего синхронизированного обновления. Но в отношении любого синхронного кода, который вызывается непосредственно после вызова .animate, любой обратный вызов .animate всегда будет происходить асинхронно после завершения завершающего синхронного кода. Это означает, что завершающий код синхронизации может привести к задержке выполнения обратного вызова. - person gray state is coming; 08.09.2012

В 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
comment
привет, я закрывал некоторые вкладки и проверял этот вопрос на наличие обновлений и чувствовал себя плохо, потому что вы дали такой подробный ответ, и никто вообще не ответил. многое из того, что вы сказали, я знаю, хотя я в основном программирую на javascript. я знаю, что javascript не касается процессора напрямую, и я знаю, как родео-потоки и о CLR (im .net). это точно так же, как вы потратили много времени, говоря что-то, потому что вы, казалось, не уважали знания кого-то, задающего вопрос о глупом старом javascript. вы, очевидно, очень хорошо все это знаете и хотите помочь начинающим программистам. так что спасибо тебе. - person dolphone bubleine; 08.09.2012