Укажите, что запущена функция JS с большой нагрузкой на процессор (спиннеры GIF не анимируются)

Отображение, а затем скрытие анимированных GIF-индикаторов / счетчиков — это хороший способ показать пользователю, что его действие сработало и что что-то происходит, пока он ожидает завершения своего действия — например, если действие требует загрузки некоторых данных с сервера (серверов). ) через AJAX.

Моя проблема заключается в том, если причиной замедления является процессоринтенсивная функция, gif зависает.

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

пример JSBIN

Примечание: кнопка «Это медленно» на какое-то время свяжет процессор — у меня около 10 секунд, зависит от характеристик ПК. Вы можете изменить степень этого с помощью атрибута data-reps в HTML.

  введите здесь описание изображения

  • Ожидание: при нажатии запускается анимация. Когда процесс завершится, текст изменится (обычно мы бы тоже скрыли индикатор, но пример будет понятнее, если мы оставим его вращающимся).
  • Фактический результат: анимация запускается, затем останавливается до завершения процесса. Это создает впечатление, что что-то сломано (пока вдруг неожиданно не завершится).

Есть ли способ указать, что запущенный процесс не зависает, если JS загружает процессор? Если нет возможности анимировать что-то, я прибегаю к отображению, а затем скрытию статического текстовое сообщение с надписью Loading... или что-то подобное, но что-то анимированное выглядит гораздо активнее.


Если кто-то задается вопросом, почему я использую код, интенсивно использующий процессор, а не просто избегаю проблемы путем оптимизации: это очень сложный рендеринг. Код довольно эффективен, но то, что он делает, сложно, поэтому он всегда будет требователен к процессору. Это занимает всего несколько секунд, но этого достаточно, чтобы разочаровать пользователя, и of-activity-indicators-progress-b">давным-давно было проведено множество исследований, доказывающих, что индикаторы хороши для UX.


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

  • пример JSBIN.
  • Одно простое исправление, которое я нашел здесь (используемое в другом примере выше), состоит в том, чтобы обернуть все после отображения индикатора в setTimeout( function(){ ... },50); с очень коротким интервалом, чтобы сделать его асинхронным. Это работает (см. первый пример выше), но это не очень чисто - я уверен, что есть лучший подход.

Я уверен, что должен быть какой-то стандартный подход к индикаторам для загрузки процессора, о котором я не знаю, или, может быть, это нормально просто использовать Loading... текст с setTimeout? Мои поиски ничего не дали. Я прочитал 6 или 7 вопросов о похожих проблемах, но все они оказались несвязанными.


Изменить Несколько замечательных предложений в комментариях, вот еще несколько подробностей моей конкретной проблемы:

  • Сложный процесс включает в себя обработку больших файлов данных JSON (например, операции манипулирования данными JS в памяти после загрузки файлов) и визуализацию SVG (через Raphael.js), включая сложную, подробную масштабируемую карту мира. , по результатам обработки данных из JSON. Итак, некоторые из них требуют манипулирования DOM, некоторые — нет.
  • К сожалению, мне нужно поддерживать IE8, НО если необходимо, я могу предоставить пользователям IE8/IE9 минимальный запасной вариант, например текст Loading..., а всем остальным дать что-то современное.

person user56reinstatemonica8    schedule 21.11.2013    source источник
comment
Вы пробовали CSS-анимацию?   -  person Ross Allen    schedule 21.11.2013
comment
Задумывались ли вы о переносе вашего вычислительно затратного кода на Web Worker?   -  person Pointy    schedule 21.11.2013
comment
@ssorallen Хорошая идея - обычно я даже не думаю об анимации CSS3, так как от меня требуется поддержка IE8+ (ооооо), но если это сработает, пользователи IE‹10 могут иметь Loading... текст, а все остальные могут получить CSS3.   -  person user56reinstatemonica8    schedule 21.11.2013
comment
@Pointy - интересно, раньше таких не встречал, сейчас гуглю... Параграф 2 этой статьи от John Resig похоже на то, что я ищу.   -  person user56reinstatemonica8    schedule 21.11.2013
comment
@ user568458 это похоже на использование отдельного потока. Вы должны передавать сообщения в/из кода веб-работника, поэтому для некоторых приложений это сложно использовать. Механизм должен держать среды изолированными из-за отсутствия в языке примитивов синхронизации.   -  person Pointy    schedule 21.11.2013
comment
К сожалению, Web Workers поддерживаются только в IE10+: caniuse.com/#feat=webworkers   -  person Ross Allen    schedule 24.11.2013
comment
Я наткнулся на хорошую статью, в которой анимация css3 продолжает работать в определенных браузерах, несмотря на то, что js работает довольно интенсивно: phpied.com/css-animations-off-the-ui-thread Я не совсем уверен, может ли это быть выполнимым решением 4 для вас, но я протестировал html с Стандартный браузер Android, а красные и зеленые кубы продолжали выполнять свои переходы при нажатии кнопки уничтожения.   -  person TorchMan    schedule 19.12.2013
comment
Я чувствовал себя так свободно, чтобы улучшить вашу скрипку. Я тестировал его с FF, но все зависает. Но в Chrome красные и зеленые кубики продолжали улыбаться jsbin.com/iCEsoqID/ 5/изменить   -  person TorchMan    schedule 19.12.2013
comment
Ха-ха-ха, возвращаясь к этому вопросу три года спустя, я так ошибся, когда сказал, что код довольно эффективен! Кроме того, профилировщик визуальной памяти Chrome Developer Tools в разделе «Временная шкала» › отметьте «Память» невероятно.   -  person user56reinstatemonica8    schedule 13.09.2016


Ответы (2)


Современные браузеры теперь запускают анимацию CSS независимо от потока пользовательского интерфейса, если анимация реализована с использованием преобразования, а не путем изменения свойств. Статью об этом можно найти по адресу http://www.phpied.com/css-animations-off-the-ui-thread/.

Например, реализованы некоторые счетчики CSS на http://projects.lukehaas.me/css-loaders/. с преобразованиями и не зависнет, когда поток пользовательского интерфейса занят (например, последний счетчик на этой странице).

person Bob Arlof    schedule 21.11.2015
comment
Имейте в виду, что не так просто убрать анимацию из потока пользовательского интерфейса. Если анимированный элемент имеет какую-либо относительную единицу (например, процент), анимация все равно зависнет. - person leods92; 08.07.2016
comment
Интересно, что в Chrome № 2, № 3 и № 8 продолжают вращаться на странице Люка Хааса, если я испорчу процессор с помощью var start = +new Date; while (+new Date - start < 2000){}; в IE10 и IE11 продолжает вращаться только #6, а в Firefox продолжают вращаться #2 и #6... тем временем все браузеры ведут себя одинаково с простыми квадратами - person user56reinstatemonica8; 13.09.2016
comment
... немного больше тестирования позже, кажется, что все современные (IE10+ и ~ 2014+ версии других браузеров, более или менее) браузеры позволяют анимацию, которая является только преобразованиями, и браузеры также позволяют некоторые другие вещи, но они настолько непоследовательны в том, что они допускают, что попытка уследить за всем этим превращается в безумие. Короче говоря, используйте анимацию преобразования CSS. - person user56reinstatemonica8; 13.09.2016
comment
Последнее замечание (!) — в некоторых браузерах (особенно во всех версиях IE) даже счетчики, полностью основанные на transform, зависнут, если ЦП выполняет большое количество событий слоя рисования/рендеринга, что может вызвать проблемы UX, например. процесс загружает файл по AJAX, спиннер крутится; он обрабатывает данные, счетчик все еще вращается, если он основан только на преобразованиях; он начинает рендерить сложный новый макет, счетчик перестает вращаться, как будто он разбился. - person user56reinstatemonica8; 15.09.2016

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

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

person InvisibleBacon    schedule 19.12.2013