Можем ли мы считать requestAnimFrame «выходом» цикла приложения, позволяющим обрабатывать цикл событий?
-
21-12-2019 - |
Вопрос
я использую requestAnimFrame
метод в JavaScript, чтобы обновить холст в основном цикле моей программы:
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function animate() {
requestAnimationFrame( animate );
//var runcount = 100;
//for (var i=0;i<=100;i++) {
draw();
// if (runcount === i)
// alert("Completed program loop");
// }
}
То, что происходило, заключалось в том, что моя программа, которая обновляла холст только после того, как мой основной цикл выполнился 100 итераций, а затем остановился.После того, как я добавлю метод выше в мой основной цикл, внезапно я получаю обновления холста в каждом цикле моей программы.
Тот факт, что холст не обновлялся до завершения моей программы, заставил меня подумать, что обновление холста выполняется в другом потоке, который не имеет приоритета.(Но мы знаем, что JavaScript является однопоточным).
Мой вопрос - Можем ли мы считать requestAnimFrame «выходом» цикла приложения, позволяющим обрабатывать цикл событий? Могу ли я по-прежнему считать, что JavaScript является однопоточным?
Решение
Вы не уточнили, как вы выполнили итерацию 1000 раз, но я предполагаю, что вы имеете в виду, что вы выполняли итерацию с использованием for
или while
петля (?поправьте меня если я ошибаюсь..).
Когда вы выполняете цикл for/ while, скрипт будет выполняться до тех пор, пока этот цикл (или область действия) не завершится.Поскольку JS, как вы знаете, является однопоточным, он не может обрабатывать такие вещи, как очередь событий, пока он это делает, поэтому ничто не сможет обновляться (включая.DOM) до тех пор, пока цикл не завершится (вообще говоря, может существовать специфичная для браузера реализация, которая разрешает обновления DOM, если обновления DOM запускаются, например, в отдельном потоке, но это отдельная вещь от JS).
Теперь, когда вы реализовали rAF, вы выполняете одну итерацию для каждого рамка.Это означает, что у браузера есть время обработать очередь событий. асинхронно (не то же самое, что многопоточный), если только код, который вы обрабатывали в цикле, также некоторое время не выполнял цикл занятости, что создало бы тот же сценарий, что и первый.
Вы могли бы использовать setTimeout
также.Что раф делает иначе чем например setTimeout
или setInterval
заключается в том, что это эффективная низкоуровневая реализация механизма таймера, способного синхронизироваться с монитором. ВПУСТОЙ период (вертикальное гашение, которое видеокарта выполняет с помощью опции, называемой vsync) - что означает, простым словом, частоту обновления монитора (обычно 60 Гц).Это позволяет нам создавать плавную анимацию, поэтому она называется request*Animation*Frame, поскольку именно для этого она и создана.
JS все еще однопоточный?Да, это не изменится (единственный способ добиться многопоточности в JS — использовать Web Workers).
РАФ что-то меняет?Не в этой области — это более точная и производительная альтернатива setTimeout
и он синхронизируется по-другому, но это все.Он будет страдать от тех же ограничений, что и setTimeout
невозможность запуска, если область занята (следовательно, request
* часть имени, которая не подразумевает никаких гарантий), но когда она сработает, она будет синхронизирована с частотой обновления монитора.