0

Я использую requestAnimFrame method в JavaScript, чтобы сделать мое обновление холста в основном цикле моей программы:Можем ли мы рассмотреть requestAnimFrame a 'yield' в цикле приложения, чтобы разрешить цикл события?

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"); 
// } 
} 

Что происходит в том, что my program that only updated the canvas after my main loop had run for 100 итераций, а затем остановились. После добавления method above into my main loop, suddenly I get canvas updates в каждый цикл моей программы.

Тот факт, что полотно не обновлялось до завершения моей программы, заставило меня подумать, что обновление холста работает в другом потоке, который не получил приоритет. (Но мы знаем, что JavaScript is single-threaded).

Мой вопрос - Можем ли мы рассмотреть запросAnimFrame a 'yield' в цикле приложения, чтобы разрешить цикл обработки событий? Могу ли я считать, что JavaScript однопоточный?

+0

Это не * изменение * ничего, это всего лишь обратный звонок для вашего кода. И, да, JS по-прежнему однопоточный – zerkms

+0

ваш вопрос непонятен. «он» ничего не обновляет. Непонятно, что вы имеете в виду, говоря «почему он не обновил холст, когда он работал в любом случае»? – zerkms

+0

я отредактировал, чтобы ответить на ваши изменения. – GameAlchemist

ответ

1

Вы не знаете, как вы делали свою итерацию 1000 раз, но я предполагаю, что вы имеете в виду, что вы повторили с помощью цикла или while («исправьте меня, если я ошибаюсь ..»).

Когда вы выполняете цикл for/while, скрипт будет занят циклом до тех пор, пока этот цикл (или область) не завершится. Поскольку JS, как вы знаете, однопоточный, он не может обрабатывать такие вещи, как очередь событий, пока он это делает, поэтому ничего не сможет обновить (включая DOM) до тех пор, пока цикл не завершится (вообще говоря, может быть определен браузер которые допускают обновления DOM, если обновления DOM выполняются, например, в отдельном потоке, но это отдельная вещь от JS).

Теперь, когда вы внедрили rAF, вы делаете одиночную итерацию за кадр. Это означает, что браузер имеет время для обработки очереди событий асинхронно (не такой, как многопоточность), если только код, обработанный в цикле, не занялся циклом занятости, а создавал бы тот же сценарий, что и первый.

Возможно, вы использовали setTimeout. Что делает rAF иначе, чем, например, setTimeout или setInterval, так это то, что это эффективная низкоуровневая реализация механизма таймера, который может синхронизироваться с периодом VBLANK монитора (вертикальное гашение, которое вещает видеокарта через опцию, называемую vsync), что означает обычное слово частота обновления монитора (обычно 60 Гц). Это позволяет нам создавать плавную анимацию (и), и поэтому она называется request * Animation * Frame, поскольку это то, для чего она предназначена в первую очередь.

Является ли JS еще однопоточным? Да, это не изменится (единственный способ добиться многопоточности в JS - это использование веб-рабочих).

Что-нибудь изменить? Не в этой области - это более точная и эффективная альтернатива setTimeout, и она синхронизируется по-разному, но это все. Он будет иметь те же ограничения, что и с setTimeout, который не может быть запущен, если область занята (следовательно, часть request *, которая не подразумевает никакой гарантии), но когда она срабатывает, она будет синхронизироваться с частотой обновления монитора.

+0

Хорошо - можем ли мы рассмотреть rAF a 'yield' в цикле приложения, чтобы разрешить цикл события? – hawkeye

+0

Результат @hawkeye приостанавливает целевой поток, который становится немного иным, поскольку только один из rAF и main может выполняться в любой момент времени. Если rAF занят, main не может выполнить и vica versa. Единственное различие заключается в том, что rAF может синхронизироваться на низкоуровневом уровне (с таймером высокой точности и с помощью аппаратного обеспечения), но кроме этого он выполняет то же самое, что, например, setTimeout (вроде «get in line»). Но какая-то грубая тактика по отношению к обычной очереди событий необходима, чтобы позволить ей работать вовремя. – K3N

+0

что случилось @hawkeye, все нормально? Мы потратили некоторое время, отвечая на ваш вопрос, это также поможет будущим посетителям. Какую конкретную причину вы хотите удалить? Почему бы не вернуться и посмотреть, можно ли улучшить текст? Дайте мне знать .. – K3N