Подтвердить что ты не робот

Предотвращение блокировки браузера с помощью javascript

У меня есть JavaScript, который выполняет множество вычислений, а также чтение/запись значений из/в DOM. Страница огромна, так что это часто заканчивается блокировкой браузера в течение минуты (иногда дольше с IE) при 100% использовании ЦП.

Есть ли какие-нибудь ресурсы для оптимизации JavaScript, чтобы это не происходило (все, что я могу найти, это как отключить предупреждение Firefox script)?

4b9b3361

Ответ 1

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

Например, что-то вроде этого...

function doCalculation()
{
   //do your thing for a short time

   //figure out how complete you are
   var percent_complete=....

   return percent_complete;
}

function pump()
{
   var percent_complete=doCalculation();

   //maybe update a progress meter here!

   //carry on pumping?
   if (percent_complete<100)
   {
      setTimeout(pump, 50);
   }
}

//start the calculation
pump();

Ответ 2

Использовать таймауты.

Поместив содержимое вашего цикла (ов) в отдельные функции и вызывая их из setTimeout() с тайм-аутом 50 или около того, javascript даст управление потоком и вернется через некоторое время, разрешив интерфейс пользователя чтобы получить внешний вид.

Там будет хорошая проработка здесь.

Ответ 3

Я когда-то писал о производительности в браузере, но позвольте мне кратко изложить те, которые связаны с DOM для вас здесь.

  • Обновляйте DOM как можно реже. Внесите свои изменения в объекты DOM в памяти и добавьте их только один раз в DOM.
  • Используйте innerHTML. Это быстрее, чем методы DOM в большинстве браузеров.
  • Используйте делегирование событий вместо обычной обработки событий.
  • Знайте, какие вызовы дороги, и избегайте их. Например, в jQuery значение $( "div.className" ) будет дороже $( "# someId" ).

Затем некоторые из них связаны с самим JavaScript:

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

Там еще несколько в моем блоге (ссылка выше).

Ответ 4

Это все еще немного кровоточит, но Firefox 3.5 имеет такие вещи, которые называются веб-рабочими, но я не уверен в их поддержке в других браузерах.

г. У Resig есть статья о них здесь: http://ejohn.org/blog/web-workers/

И Simulated Annealing, вероятно, самый простой пример, если вы заметите, что вращающийся логотип Firefox не замерзает, когда рабочие потоки выполняют свои запросы (таким образом, не замораживая браузер).

Ответ 5

Вы можете попробовать выполнить долговременные вычисления в потоках (см. JavaScript и темы), хотя они не очень переносимы.

Вы также можете попробовать использовать какой-либо Javascript-профайлер, чтобы найти узкие места производительности. Firebug поддерживает профилирование javascript.

Ответ 6

Мой опыт заключается в том, что манипуляции с DOM, особенно в IE, гораздо более важны для производительности, чем "основной" JavaScript (цикл и т.д.).

Если вы создаете узлы, в IE это намного быстрее, создавая строку HTML, а затем устанавливая innerHTML в контейнере, чем с помощью методов DOM, таких как createElement/appendChild.

Ответ 7

Вы можете попытаться сократить код

 $(xmlDoc).find("Object").each(function(arg1) {
    (function(arg1_received) {
                setTimeout(function(arg1_received_reached) {

                    //your stuff with the arg1_received_reached goes here 

                }(arg1_received), 0)
            })(arg1)
}(this));

или для циклов "для" попробуйте

for (var i = 0 ; i < 10000 ; i = i + 1) {
    (function(arg1_received) {
        setTimeout(function(arg1_received_reached) {

            //your stuff with the arg1_received_reached goes here 

        }(arg1_received), 0)
    })(arg1_to_send)
}

У меня была такая же проблема, и мои клиенты сообщали об этом как об ошибке "Убить страницу". Но теперь я получил лучшее решение для этого.:)