2012-12-17 4 views
0

Я хотел бы постоянно выполнять часть кода JavaScript на странице, проводя все доступное мне время ЦП, но позволяя браузеру функционировать и реагировать на в то же время.Самый эффективный способ дребезжать непрерывное выполнение JavaScript на веб-странице

Если я просто запускаю свой код непрерывно, он зависает от пользовательского интерфейса браузера, и браузер начинает жаловаться. Прямо сейчас я пропускаю нулевой тайм-аут до setTimeout, который затем выполняет небольшой кусок работы и возвращается к setTimeout. Это работает, но, похоже, не использует весь доступный процессор. Какие-нибудь лучшие способы сделать это, о которых вы могли бы подумать?

Обновление: Чтобы уточнить, код, о котором идет речь, представляет собой кадры рендеринга на canvas непрерывно. Единицей работы здесь является один кадр. Мы стремимся к максимально возможной частоте кадров.

+0

Это потому, что большинство браузеров не допускают интервал javascript 0мс. Они закрывают его в 20 мс или что-то в этом роде. –

+0

Это похоже на довольно плохую идею в целом, но, возможно, не для ваших целей.Можете ли вы рассказать нам о том, что делает ваш код, который вы используете постоянно? – hobberwickey

+0

@hobberwickey: Это рендеринг графики на холсте и нацелен на максимально возможную частоту кадров. – dragonroot

ответ

0

Можно использовать window.postMessage(), чтобы преодолеть ограничение на минимальное время, установленное setTimeout. См. this article. Демо доступно here.

2

веб-рабочие что-то попробовать

https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers 
+0

Спасибо! Это может быть применимо, однако код рисуется на странице, что, вероятно, не то, что может сделать рабочий. Я ожидаю, что работник должен будет сообщить все результаты в поток пользовательского интерфейса, что добавит дополнительную работу как для программиста, так и для браузера. – dragonroot

3

Возможно, что вы хотите, чтобы централизовать все, что происходит на этой странице и использовать requestAnimationFrame, чтобы сделать все рисунок. Поэтому в основном вы бы функция/класс, который выглядит примерно так (вы должны простить некоторые/синтаксические ошибки стиля Привык классы Mootools, просто принять это как контур)

var Main = function(){ 
    this.queue = []; 
    this.actions = {}; 

    requestAnimationFrame(this.loop) 
} 

Main.prototype.loop = function(){ 
    while (this.queue.length){ 
     var action = this.queue.pop(); 
     this.executeAction(e); 
    } 

    //do you rendering here 
    requestAnimationFrame(this.loop); 
} 

Main.prototype.addToQueue = function(e){ 
    this.queue.push(e); 
} 

Main.prototype.addAction = function(target, event, callback){ 
    if (this.actions[target] === void 0) this.actions[target] = {}; 
    if (this.actions[target][event] === void 0) this.actions[target][event] = []; 

    this.actions[target][event].push(callback); 
} 

Main.prototype.executeAction = function(e){ 
    if (this.actions[e.target]!==void 0 && this.actions[e.target][e.type]!==void 0){ 
     for (var i=0; i<this.actions[e.target][e.type].length; i++){ 
      this.actions[e.target][e.type](e); 
     } 
    } 
} 

Так в основном вы должны использовать этот класс для обработки всего, что происходит на странице. Каждый обработчик событий будет onclick='Main.addToQueue(event)' или, тем не менее, вы хотите добавить свои события на свою страницу, просто укажите им, чтобы добавить событие в реплику, и просто используйте Main.addAction, чтобы направить эти события на то, что вы хотите, чтобы они делали. Таким образом, каждое действие пользователя выполняется, как только ваш холст будет завершен, и прежде чем он снова будет перерисован. До тех пор, пока ваш холст окажется на достойной частоте кадров, ваше приложение должно оставаться отзывчивым.

EDIT: забыл «это» в requestAnimationFrame (this.loop)

+0

Спасибо. Но вы упоминали «onclick»? Должен ли я заставить пользователя нажимать на странице все время для продвижения кода? Я не совсем понимаю, как и когда код действительно будет выполняться там. Мне нужна веб-страница для запуска без какого-либо взаимодействия с пользователем - пользователь просто сидит и смотрит. – dragonroot

+0

Правильно, вы помещаете код рендеринга анимации, где я указал, и если вы хотите, чтобы произошли другие вещи (например, пользователи, нажимая на вещи или что бы они еще не сделали на странице), вы используете addToQueue для их запуска. Если пользователь ничего не делает, анимация просто играет. – hobberwickey

+0

Да, но что заставляет запускать анимацию? То есть после того, как мы отобрали один кадр, нам нужно будет остановиться (чтобы браузер мог обрабатывать интерфейс и т. Д.). После этого мы хотим, чтобы вас вызывали, чтобы отобразить другой фрейм - что вызовет этот вызов? – dragonroot

1

Вы можете настроить производительность за счет изменения объема работы вы делаете на вызов. В вашем вопросе вы говорите, что делаете «небольшой кусок работы». Установите параметр, который контролирует объем выполняемой работы и пробует различные значения.

Возможно, вы также попытаетесь установить тайм-аут до, вы делаете обработку. Таким образом, затраченная на обработку обработка должна учитывать любой минимальный набор браузеров.

Один из методов, который я использую, - иметь счетчик в моем цикле обработки, подсчитывая итерации. Затем настройте интервал, скажем одну секунду, в этой функции, отобразите счетчик и очистите его до нуля. Это обеспечивает приблизительную производительность, с помощью которой можно измерить эффекты внесенных изменений.

В целом это, вероятно, будет сильно зависеть от конкретных браузеров, даже версий браузеров. С настраиваемыми параметрами и измерениями производительности вы можете реализовать цикл обратной связи для оптимизации в реальном времени.

+0

Спасибо, это еще одно решение. Жесткая часть здесь заключается в том, что для этого требуется калибровка. Нагрузка на машину пользователя может со временем меняться, что сделает такую ​​калибровку хрупкой. Кроме того, в идеале я бы просто сделал один кадр, а затем уступил браузеру, чтобы он обрабатывал его события, затем сразу же отобразил другой кадр и так далее. То есть единица работы здесь - один кадр - трудно сделать эту единицу меньше или больше. – dragonroot

+0

Действительно, вы понимаете трудности. Я бы добавил параметр для управления количеством кадров на вызов. Проблема заключается в относительной обработке за кадр по сравнению с временем, затрачиваемым браузером, когда нечего делать. Оба они явно зависят от множества факторов, некоторые из которых могут постоянно меняться. – HBP