Violation tâche JavaScript longue durée a pris xx ms

Récemment, j'ai reçu ce genre d'avertissement, et c'est la première fois que je l'obtiens:

[Violation] Long running JavaScript task took 234ms
[Violation] Forced reflow while executing JavaScript took 45ms

Je travaille sur un projet de groupe et je n'ai aucune idée d'où ça vient. ce n'est jamais arrivé avant. Soudain, il apparaît quand quelqu'un d'autre impliqué dans le projet. Comment puis-je trouver quel fichier/fonction provoque un tel avertissement? J'ai cherché une réponse, mais surtout sur la solution sur la façon de le résoudre. Je ne peux pas le résoudre si Je ne trouve même pas la source du problème.

Notes: dans ce cas l'avertissement apparaît uniquement sur chrome. J'ai essayé D'utiliser Edge, Je n'ai pas reçu d'avertissements similaires. Je ne l'ai pas encore testé sur mozilla.

Mise à jour : Je reçois même l'erreur de jquery.min.js en disant:

[Violation] Handler took 231ms of runtime (50ms allowed)            jquery.min.js:2
166
demandé sur activedecay 2016-12-19 11:29:06

11 réponses

Mise à jour: Chrome 58+ A CACHÉ ces messages et d'autres messages de débogage par défaut. Pour les afficher, cliquez sur la flèche à côté de 'Info' et sélectionnez 'Verbose'.

Mise à jour 2: Chrome 57 activé "masquer les violations" par défaut. Pour les réactiver, vous devez activer les filtres et décocher la case "Masquer les violations".

Soudain, il apparaît quand quelqu'un d'autre impliqué dans le projet

Je pense qu'il est plus probable que vous avez mis à jour Chrome 56. Cet avertissement est un (omi) merveilleuse nouvelle fonctionnalité - veuillez l'éteindre uniquement si vous êtes désespéré et que votre évaluateur vous enlèvera des marques. Les problèmes sous-jacents sont là dans les autres navigateurs, mais les navigateurs ne vous disent tout simplement pas qu'il y a un problème. Le ticket Chromium est ici mais il n'y a pas vraiment de discussion intéressante à ce sujet: https://bugs.chromium.org/p/chromium/issues/detail?id=662497

Ces messages sont des avertissements au lieu d'erreurs car cela ne va pas vraiment causer de problèmes majeurs problème. Cela peut entraîner la chute des images ou une expérience moins fluide.

Ils valent la peine d'être étudiés et réparés pour améliorer la qualité de votre application. La façon de le faire est de prêter attention aux circonstances dans lesquelles les messages apparaissent, et de faire des tests de performance pour affiner où le problème se produit. Le moyen le plus simple de commencer les tests de performance est d'insérer du code comme ceci:

function someMethodIThinkMightBeSlow() {
    const startTime = performance.now();

    // Do the normal stuff for this function

    const duration = performance.now() - startTime;
    console.log(`someMethodIThinkMightBeSlow took ${duration}ms`);
}

Si vous voulez être plus avancé, vous pouvez également utiliser le profileur de Chrome: https://developers.google.com/web/tools/chrome-devtools/rendering-tools/

Ou utiliser une bibliothèque de benchmarking comme celle-ci: https://benchmarkjs.com/

Une fois que vous avez trouvé du code qui prend beaucoup de temps (50ms est le seuil de Chrome), vous avez quelques options:

  1. découpez une partie/la totalité de cette tâche qui peut être inutile
  2. comprendre comment faire la même tâche plus rapide
  3. divisez le code en plusieurs étapes asynchrones

(1) et (2) peuvent être difficiles ou impossibles. Mais parfois vraiment facile et devrait être vos premières tentatives. Si nécessaire, il devrait toujours être possible de le faire (3). Pour ce faire, vous utiliserez quelque chose comme

setTimeout(functionToRunVerySoonButNotNow);

Ou

// This one is not available natively in IE, but there are polyfills available.
Promise.resolve().then(functionToRunVerySoonButNotNow);

, Vous pouvez en savoir plus sur la nature asynchrone de javascript ici:

Http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/

155
répondu voltrevo 2017-06-29 14:58:50

Ce ne sont que des avertissements comme tout le monde l'a mentionné. Cependant, si vous souhaitez les résoudre (ce que vous devriez faire), vous devez d'abord identifier la cause de l'avertissement. Il n'y a pas de raison unique pour laquelle vous pouvez obtenir un avertissement de refusion de force.
Quelqu'un a créé une liste pour certaines options possibles. Vous pouvez suivre la discussion pour plus d'informations.
Voici l'essentiel des raisons possibles -

Ce qui force la mise en page / refusion

Tous les ci-dessous les propriétés ou les méthodes, lorsque demandé / appelé JavaScript, déclenchera le navigateur pour calculer de manière synchrone le style et mise en page*. Ceci est également appelé refusion ou mise en page raclée , et est un goulot d'étranglement de performance commun.

Élément

Boîte métriques
  • elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent
  • elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight
  • elem.getClientRects(), elem.getBoundingClientRect()
Faites défiler les choses
  • elem.scrollBy(), elem.scrollTo()
  • elem.scrollIntoView(), elem.scrollIntoViewIfNeeded()
  • elem.scrollWidth, elem.scrollHeight
  • elem.scrollLeft, elem.scrollTop en outre, en les définissant
Concentrer
  • elem.focus() peut déclencher unedouble Mise en page forcée (source )
Également…
  • elem.computedRole, elem.computedName
  • elem.innerText (source)

GetComputedStyle

window.getComputedStyle() forcera généralement le style recalc (source)

window.getComputedStyle() forcera la mise en page, ainsi, si l'un des ce qui suit est vrai:

  1. L'élément est dans un arbre d'ombre
  2. Il existe des requêtes multimédia (liées à la fenêtre d'affichage). Plus précisément, l'une des opérations suivantes: (source) * min-width, min-height, max-width, max-height, width, height * aspect-ratio, min-aspect-ratio, max-aspect-ratio
    • device-pixel-ratio, resolution, orientation
  3. la propriété demandée est l'une des suivantes: (source )
    • height, width * top, right, bottom, left * margin [-top, -right, -bottom, -left, ou abréviation] seulement si le la marge est fixée. * padding [-top, -right, -bottom, -left, ou raccourci ] seulement si le remplissage est fixe. * transform, transform-origin, perspective-origin * translate, rotate, scale * webkit-filter, backdrop-filter * motion-path, motion-offset, motion-rotation * x, y, rx, ry

Fenêtre

  • window.scrollX, window.scrollY
  • window.innerHeight, window.innerWidth
  • {[72] } force uniquement le style

Formulaires

  • inputElem.focus()
  • inputElem.select(), textareaElem.select() (source)

Événements de la Souris

  • mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX, mouseEvt.offsetY (source)

Document

  • {[80] } force uniquement le style

Plage

  • range.getClientRects(), range.getBoundingClientRect()

SVG

Contenteditable

  • Beaucoup et beaucoup de choses, ...y compris la copie d'une image dans le presse-papiers (source)

Vérifiez plus ici .

Mise à Jour:

Robocat à partir d'observations

Plus de fond: Le chrome le code source du problème original et une discussion sur une API de performance pour les Avertissements.

39
répondu noob 2018-03-12 04:12:59

Quelques idées:

  • Supprimez la moitié de votre code (peut - être en le commentant).

    • Le problème Est toujours là? SUPER, vous avez réduit les possibilités! Répéter.

    • Le problème n'est-il pas là? OK, regardez la moitié que vous avez commentée!

  • Utilisez-vous un système de contrôle de version (par exemple, Git)? Si c'est le cas, {[0] } certains de vos commits les plus récents. Quand le problème introduit? Regardez le commit pour voir exactement quel code a changé lorsque le problème est arrivé.

20
répondu therobinkim 2016-12-19 08:34:31

Regardez dans la console Chrome sous L'onglet Réseau et trouvez les scripts qui prennent le plus de temps à charger.

Dans mon cas, il y avait un jeu Angulaire ajouter les scripts que j'avais compris, mais pas encore utilisé dans l'application :

<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>

Ce sont les seuls fichiers JavaScript qui ont pris plus de temps à charger que le temps spécifié par l'erreur "tâche longue durée".

Tous ces fichiers s'exécutent sur mes autres sites Web sans aucune erreur générée mais je recevais cette erreur" tâche longue durée" sur une nouvelle application web qui avait à peine toutes les fonctionnalités. L'erreur s'est arrêtée immédiatement après la suppression.

Ma meilleure supposition est que ces add-ons angulaires cherchaient récursivement dans des sections de plus en plus profondes du DOM pour leurs balises de départ-n'en trouvant aucune, ils ont dû traverser L'ensemble du DOM avant de quitter, ce qui a pris plus de temps que Chrome attend-donc l'avertissement.

5
répondu Jordan Reddick 2017-03-16 15:21:32

Cela pourrait provenir de Chrome 56 beta si vous l'utilisez.

, Mais il n'est pas sur le changelog: https://blog.chromium.org/2016/12/chrome-56-beta-not-secure-warning-web.html

Vous pouvez le masquer dans la barre de filtre de la console avec la case à cocherMasquer les violations .

3
répondu Bastien 2017-01-03 13:12:08

1 est arrivé à la Console

2 Cliquez sur l'icône de filtre près (case à cocher" Journal de conservation")

3 Cochez La Case "Masquer La Violation"


Modifier

Cette fonctionnalité est supprimée de Chrome 58

Modifiez la liste déroulante du niveau de journalisation sur Verbose pour voir les violations.

3
répondu Sajan 2017-05-22 06:48:52

Dans mon cas, j'ai découvert que c'était en fait causé par Adblock.

J'ai exécuté mon application et l'ai enregistrée dans onglet Performance {[2] } dans Chrome.

Là, vous pouvez vérifier diverses fonctions qui ont pris beaucoup de temps à exécuter. Celui qui corelated avec des avertissements dans la console provenait d'un fichier qui a été chargé par l'extension Adblock.

Vérifiez ces fichiers et essayez d'identifier s'il s'agit d'un code d'extensions ou du vôtre

3
répondu Matt Leonowicz 2017-11-13 11:15:07

Si vous utilisez le canary chrome, il suffit de cocher l'option' Masquer les violations'.voir ici

2
répondu zhaoming 2017-01-24 09:57:16

J'ai trouvé une solution dans le code source D'Apache Cordova. Ils implémentent comme ceci:

var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };

Implémentation Simple, mais de manière intelligente.

Sur Android 4.4, utilisez Promise. Pour les navigateurs plus anciens, utilisez setTimeout()


Utilisation:

nextTick(function() {
  // your code
});

Après avoir inséré ce code d'astuce, tous les messages d'avertissement ont disparu.

2
répondu wf9a5m75 2017-11-16 03:19:55

J'ai trouvé la racine de ce message dans mon code. Fonctionnalité: recherche qui masquent / afficher les nœuds (hors ligne). Était:

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');
});

Dans l'onglet Performances (profileur): Chromium performance profiler layour recalcul refusion

Maintenant:

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'));
});

Dans l'onglet Performances (profileur): Chrome profiler foncé

Et je pense que maintenant la recherche fonctionne plus rapidement (229 nœuds).

2
répondu Vitaly Zdanevich 2018-03-02 09:17:03

Vous devez avoir un sélecteur de classe répété qui est recherché repeteatedly par javascript. Si quelque chose doit utiliser un id, utilisez - le comme id, pas comme une classe. Qui s'est vraiment passé pour moi.

-3
répondu Sterling Diaz 2018-01-06 03:29:07