Нарушение длительное выполнение задачи JavaScript заняло xx МС
недавно я получил такое предупреждение, и это мой первый раз получаю это:
[Violation] Long running JavaScript task took 234ms
[Violation] Forced reflow while executing JavaScript took 45ms
Я работаю над групповым проектом, и я понятия не имею, откуда он исходит. такого раньше никогда не было. Вдруг он появляется, когда кто-то участвует в проекте. Как найти, какой файл / функция вызывает такое предупреждение? Я искал ответ, но в основном о решении о том, как его решить. Я не могу решить, если я даже не могу найти источник проблема.
Примечания: в этом случае предупреждение появляется только на chrome. Я попытался использовать Edge, не получил никаких подобных предупреждений. Я еще не тестировал его на mozilla.
обновление :
Я даже получаю ошибку jquery.min.js говорю:
[Violation] Handler took 231ms of runtime (50ms allowed) jquery.min.js:2
11 ответов:
обновление: Chrome 58 + скрыл эти и другие отладочные сообщения по умолчанию. Чтобы отобразить их, нажмите стрелку рядом с "информация" и выберите "подробный".
обновление 2: Chrome 57 включен "скрыть нарушения" по умолчанию. Чтобы включить их снова, вам нужно включить фильтры и снять флажок "скрыть нарушения".
вдруг он появляется, когда кто-то участвует в проекте
Я думаю, что это более вероятно, что вы обновлены до Хром 56. Это предупреждение является (ИМО) замечательной новой функцией - пожалуйста, только выключите его, если вы в отчаянии, и ваш асессор заберет у вас метки. Основные проблемы существуют в других браузерах, но браузеры просто не говорят вам, что есть проблема. Билет Chromium здесь, но на самом деле нет никакого интересного обсуждения: https://bugs.chromium.org/p/chromium/issues/detail?id=662497
эти сообщения являются предупреждениями, а не ошибками потому что это не вызовет серьезных проблем. Это может привести к тому, что кадры будут отброшены или иначе вызовут менее гладкий опыт.
Они заслуживают изучения и фиксации, чтобы улучшить качество вашего приложения, однако. Чтобы сделать это, обратите внимание на то, какие обстоятельства появляются сообщения, и выполните тестирование производительности, чтобы сузить область возникновения проблемы. Самый простой способ начать тестирование производительности-вставить некоторый код, например это:
function someMethodIThinkMightBeSlow() { const startTime = performance.now(); // Do the normal stuff for this function const duration = performance.now() - startTime; console.log(`someMethodIThinkMightBeSlow took ${duration}ms`); }Если вы хотите получить более продвинутый, вы также можете использовать профилировщик в Chrome : https://developers.google.com/web/tools/chrome-devtools/rendering-tools/
или использовать библиотеку бенчмаркинга, как этот: https://benchmarkjs.com/
как только вы нашли какой-то код, который занимает много времени (50 мс-это порог Chrome), у вас есть несколько вариантов:
- вырезать некоторые/все из этой задачи это может быть ненужным
- выяснить, как сделать ту же задачу быстрее
- разделите код на несколько асинхронных шагов
(1) и (2) может быть затруднено или невозможно. Но иногда действительно легко и должны быть ваши первые попытки. При необходимости это всегда можно сделать (3). Для этого вы будете использовать что-то вроде
setTimeout(functionToRunVerySoonButNotNow);или
// This one is not available natively in IE, but there are polyfills available. Promise.resolve().then(functionToRunVerySoonButNotNow);вы можете прочитать больше об асинхронной природе javascript здесь:
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
это просто предупреждения, как все упоминали. Однако, если вы заинтересованы в решении этих проблем (что вы должны), то вам нужно сначала определить, что вызывает предупреждение. Нет ни одной причины, из-за которой вы можете получить предупреждение о принудительном оплавлении.
Кто-то создал список для некоторых возможных вариантов. Вы можете следить за обсуждением для получения дополнительной информации.
Вот суть возможных причин -что заставляет макет / оплавления
все приведенные ниже свойства или методы, при запросе / вызове В JavaScript, будет запускать браузер, чтобы синхронно рассчитать стиль и макет*. Это также называется reflow или макет обмолот, и общая производительность.
элемент
Метрики коробкиПрокрутить материал
elem.offsetLeft,elem.offsetTop,elem.offsetWidth,elem.offsetHeight,elem.offsetParentelem.clientLeft,elem.clientTop,elem.clientWidth,elem.clientHeightelem.getClientRects(),elem.getBoundingClientRect()Фокусировать
elem.scrollBy(),elem.scrollTo()elem.scrollIntoView(),elem.scrollIntoViewIfNeeded()elem.scrollWidth,elem.scrollHeightelem.scrollLeft,elem.scrollTopкроме того, установив ихТакже…
elem.focus()может вызвать a double принудительное макет (источник)
elem.computedRole,elem.computedNameelem.innerText(источник)getComputedStyle
window.getComputedStyle()обычно принудительно пересчитывает стиль (источник)
window.getComputedStyle()заставит макет, а также, если любой из верно следующее:
- элемент находится в тени дерева
- есть медиа-запросы (связанные с видовым экраном). Конкретно, один из следующих вариантов: (источник)*
min-width,min-height,max-width,max-height,width,height*aspect-ratio,min-aspect-ratio,max-aspect-ratio
device-pixel-ratio,resolution,orientation- запрошенное свойство является одним из следующих: (источник)
height,width*top,right,bottom,left*margin[-top,-right,-bottom,-left, или сокращение] только если маржа фиксированная. *padding[-top,-right,-bottom,-left, или сокращение] только если прокладка исправлена. *transform,transform-origin,perspective-origin*translate,rotate,scale*webkit-filter,backdrop-filter*motion-path,motion-offset,motion-rotation*x,y,rx,ryокно
window.scrollX,window.scrollYwindow.innerHeight,window.innerWidthwindow.getMatchedCSSRules()только сил стильформы
inputElem.focus()inputElem.select(),textareaElem.select()(источник)событий мыши
mouseEvt.layerX,mouseEvt.layerY,mouseEvt.offsetX,mouseEvt.offsetY(источник)документ
doc.scrollingElementтолько силы стиляряд
range.getClientRects(),range.getBoundingClientRect()SVG
- довольно много; не исчерпывающий список , но Tony Gentilcore в 2011 году макет запуска Список указал на несколько.
contenteditable
- много и много вещей, ... в том числе копирование изображения в буфер обмена (источник)
узнать больше здесь.
обновление:
robocat комментарии
больше фона: исходный код хрома из оригинальный вопрос и а обсуждение API производительности для предупреждения.
пара идей:
удалите половину вашего кода (возможно, комментируя его).
проблема все еще существует? Отлично, вы сузили возможности! Повторять.
разве проблема не в этом? Хорошо, посмотрите на половину, которую вы прокомментировали!
вы используете какую-либо систему управления версиями (например, Git)? Если так, то
git checkoutнекоторые из ваших последних коммитов. Когда была введена проблема? Посмотрите на фиксацию, чтобы увидеть, какой именно код изменился, когда проблема впервые появилась.
посмотрите в консоли Chrome на вкладке Сеть и найдите скрипты, которые дольше всего загружаются.
в моем случае был набор угловых добавить на скрипты, которые я включил, но еще не используется в приложении:
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-utils/0.1.1/angular-ui-utils.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-animate.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-aria.min.js"></script>Это были единственные файлы JavaScript, загрузка которых заняла больше времени, чем указано в ошибке" Long Running Task".
все эти файлы работают на других моих сайтах без ошибок, но я получаю это Ошибка "Long Running Task" в новом веб-приложении, которое едва ли имело какую-либо функциональность. Ошибка остановилась сразу же после удаления.
мое лучшее предположение заключается в том, что эти угловые дополнения рекурсивно просматривали все более глубокие секции DOM для их начальных тегов - не находя ни одного, они должны были пройти весь DOM перед выходом, что заняло больше времени, чем ожидает Chrome, - таким образом, предупреждение.
Это может быть из Chrome 56 beta, если вы его используете.
но это не в списке изменений:https://blog.chromium.org/2016/12/chrome-56-beta-not-secure-warning-web.html
вы можете скрыть это в панели фильтров консоли с помощью скрыть нарушения.
1 добрался до консоли
2 щелкните значок фильтра рядом (флажок "сохранить журнал")
3 клеща "Скрыть Нарушения" флажок
EDIT
эта функция удалена из Chrome 58
измените раскрывающийся список уровень ведения журнала на подробный, чтобы увидеть нарушения.
в моем случае, я обнаружил, что это было на самом деле вызвано Adblock.
Я запустил свое приложение и записал его в производительность в Chrome.
здесь вы можете проверить различные функции, которые заняли много времени. Тот, который corelated с предупреждениями в консоли был из файла, который был загружен расширением Adblock.
проверьте эти файлы и попробуйте определить, если это какой-то код расширения или ваш
Если вы используете chrome canary, просто проверьте опцию "скрыть нарушения".посмотреть здесь
Я нашел решение в исходном коде Apache Cordova. Они реализуют так:
var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve(); var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };простая реализация, но умный способ.
над Android 4.4, используйте
Promise. Для старых браузеров используйтеsetTimeout()
использование:
nextTick(function() { // your code });после вставки этого кода трюк, все предупреждения исчезли.
Я нашел корень этого сообщения в мой код. Функциональность: поиск, который скрывает / показывает узлы (в автономном режиме). Было:
search.addEventListener('keyup', function() { for (const node of nodes) if (node.innerText.toLowerCase().includes(this.value.toLowerCase())) node.classList.remove('hidden'); else node.classList.add('hidden'); });На вкладке Производительность (профилировщик):
теперь:
search.addEventListener('keyup', function() { const nodesToHide = []; const nodesToShow = []; for (const node of nodes) if (node.innerText.toLowerCase().includes(this.value.toLowerCase())) nodesToShow.push(node); else nodesToHide.push(node); nodesToHide.forEach(node => node.classList.add('hidden')); nodesToShow.forEach(node => node.classList.remove('hidden')); });На вкладке Производительность (профилировщик):
и я чувствую, что теперь поиск работает быстрее (229 узлов).
У вас должен быть повторяющийся селектор класса, который выполняется повторно с помощью javascript. Если что-то должно использовать идентификатор, используйте его как идентификатор, а не как класс. Это случилось со мной.


Comments