ChatGPT解决这个技术问题 Extra ChatGPT

违规长时间运行的 JavaScript 任务花费了 xx 毫秒

最近,我收到了这样的警告,这是我第一次得到它:

[违规] 长时间运行 JavaScript 任务耗时 234ms [违规] 执行 JavaScript 时强制回流耗时 45ms

我正在做一个小组项目,我不知道这是从哪里来的。这以前从未发生过。突然,当其他人参与了该项目时,它出现了。如何找到导致此警告的文件/功能?我一直在寻找答案,但主要是关于如何解决它的解决方案。如果我什至找不到问题的根源,我就无法解决它。

在这种情况下,警告只会出现在 Chrome 上。我尝试使用 Edge,但没有收到任何类似的警告,而且我还没有在 Firefox 上测试过。

我什至收到来自 jquery.min.js 的错误:

[违规] 处理程序占用了 231 毫秒的运行时间(允许 50 毫秒)jquery.min.js:2

您在哪里看到此警告?你没有说你在什么环境中工作。假设一些浏览器,但是哪个浏览器等等?
@SamiKuhmonen 对此感到抱歉,我已经更新了我的问题。我用的是铬。我在 Edge 上没有发现任何类似的错误。
我只是想补充一点,2016 年末推出的这条警告消息也可能由于您在 Chrome 中安装的任何扩展程序而出现。通过在私人模式下进行测试很容易检查。
单击右侧链接,指示您发生违规的脚本,将带您到代码中发生违规的位置。
我正在使用 Ionic 4 (Angular 8),我的代码运行良好,突然这种违规行为开始出现 - 现在我的列表中没有数据显示?

F
Flimzy

更新:Chrome 58+ 默认隐藏这些和其他调试消息。要显示它们,请单击“信息”旁边的箭头并选择“详细”。

Chrome 57 默认开启“隐藏违规”。要重新打开它们,您需要启用过滤器并取消选中“隐藏违规”框。

当其他人参与该项目时,突然出现

我认为您更新到 Chrome 56 的可能性更大。在我看来,此警告是一个很棒的新功能,请仅在您绝望时将其关闭,并且您的评估员会从您那里拿走分数。其他浏览器中存在潜在问题,但浏览器并没有告诉您存在问题。 Chromium 票是 here,但实际上并没有任何有趣的讨论。

这些消息是警告而不是错误,因为它不会真正导致重大问题。它可能会导致帧丢失或以其他方式导致不太流畅的体验。

但是,它们值得研究和修复以提高应用程序的质量。做到这一点的方法是注意消息出现的情况,并进行性能测试以缩小问题发生的范围。开始性能测试的最简单方法是插入如下代码:

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's profiler,或使用像 this one 这样的基准测试库。

一旦你发现了一些需要很长时间的代码(50ms 是 Chrome 的阈值),你有几个选择:

删除部分/全部可能不必要的任务 弄清楚如何更快地完成相同的任务 将代码分成多个异步步骤

(1)和(2)可能很难或不可能,但有时真的很容易,应该是你的第一次尝试。如果需要,应该始终可以执行 (3)。为此,您将使用以下内容:

setTimeout(functionToRunVerySoonButNotNow);

或者

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

您可以阅读有关 JavaScript 的异步特性的更多信息here


只是一个建议,您可以使用 console.time (developer.mozilla.org/en-US/docs/Web/API/Console/time) console.time('UniquetLabelName') ....code here.... console.timeEnd('UniqueLabelName') 而不是使用 performance.now()
@denislexic 我想是的。不过,我不确定真正增加了什么价值。我认为了解获取当前时间并以此为基础的基本操作更有价值。
很好的答案,沃尔特雷沃!我的问题是,如果这样的代码违反了,那么它到底违反了什么?谷歌必须应用某种标准,但该标准是否在任何地方公开记录?
@Bungler Dunno,我想知道它是否也提到了一些指导方针。
@Bungler我只能猜测它是说动画代码违反了每秒至少提供60帧的规定,因此用户体验不佳。 .
R
ReinstateMonica3167040

正如每个人都提到的,这些只是警告。但是,如果您热衷于解决这些问题(您应该这样做),那么您需要首先确定导致警告的原因。没有任何一个原因会导致您收到强制回流警告。有人为一些可能的选项创建了 list。您可以关注讨论以获取更多信息。
以下是可能原因的要点:

什么强制布局/重排以下所有属性或方法,当在 JavaScript 中请求/调用时,将触发浏览器同步计算样式和布局*。这也称为回流或布局抖动,是常见的性能瓶颈。元素框指标 elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight elem.getClientRects(), elem.getBoundingClientRect() 滚动内容elem.scrollBy(), elem.scrollTo() elem.scrollIntoView(), elem.scrollIntoViewIfNeeded() elem.scrollWidth, elem.scrollHeight elem.scrollLeft, elem.scrollTop 还有,设置它们 Focus elem.focus() 可以触发双强制布局 (source) 另外… elem.computedRole, elem.computedName elem.innerText (source) getComputedStyle window.getComputedStyle() 通常会强制样式重新计算 (source) 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 请求的属性是以下之一:(源)高度、宽度 * 上、右、下、左 * 边距 [-top、-right、-bottom、-left 或简写] 仅当边距是固定的。 * 填充 [-top、-right、-bottom、-left 或简写] 仅当填充固定时。 * 变换、变换原点、透视原点 * 平移、旋转、缩放 * webkit 过滤器、背景过滤器 * 运动路径、运动偏移、运动旋转 * x、y、rx、ry 窗口 window.scrollX、窗口.scrollY window.innerHeight, window.innerWidth window.getMatchedCSSRules() 仅强制样式 Forms inputElem.focus() inputElem.select(), textareaElem.select() (source) 鼠标事件 mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX , mouseEvt.offsetY (source) 文档 doc.scrollingElement 只强制样式 Range range.getClientRects(), range.getBoundingClientRect() SVG 相当多;尚未列出详尽的清单,但 Tony Gentilcore 的 2011 布局触发清单指出了一些。 contenteditable 很多很多东西,...包括将图像复制到剪贴板(来源)

查看更多here

此外,这里是来自 original issue 的 Chromium 源代码和用于警告的 discussion about a performance API

编辑:还有一篇关于如何在 PageSpeed Insight by Google 上最小化布局重排的文章。它解释了什么是浏览器重排:

Reflow 是 Web 浏览器进程的名称,用于重新计算文档中元素的位置和几何形状,以重新渲染部分或全部文档。因为重排是浏览器中的一种用户阻塞操作,所以对于开发人员了解如何提高重排时间以及了解各种文档属性(DOM 深度、CSS 规则效率、不同类型的样式更改)对重排的影响很有帮助时间。有时重排文档中的单个元素可能需要重排其父元素以及跟随它的任何元素。

此外,它还解释了如何最小化它:

减少不必要的 DOM 深度。 DOM 树中某一层的更改会导致树的每一层都发生变化——一直到根,一直到被修改节点的子节点。这导致花费更多时间执行回流。最小化 CSS 规则,并删除未使用的 CSS 规则。如果您进行复杂的渲染更改(例如动画),请在流程之外进行。使用 position-absolute 或 position-fixed 来完成此操作。避免不必要的复杂 CSS 选择器 - 特别是后代选择器 - 这需要更多 CPU 能力来进行选择器匹配。


更多背景信息:来自 original issue 的 Chromium 源代码和用于警告的 discussion about a performance API
根据上述,只需读取 element.scrollTop 即可触发重排。这让我觉得这是一种反直觉的现象。我可以理解为什么设置 element.scrollTop 会触发回流,而只是读取它的值?如果确实是这样,有人可以进一步解释为什么会这样吗?
t
therobinkim

几个想法:

删除一半的代码(可能通过注释掉)。问题还在吗?太好了,您已经缩小了可能性!重复。问题不存在吗?好的,看看你注释掉的那一半!

问题还在吗?太好了,您已经缩小了可能性!重复。

问题不存在吗?好的,看看你注释掉的那一半!

您是否使用任何版本控制系统(例如,Git)?如果是这样,请 git checkout 一些您最近的提交。问题是什么时候引入的?查看提交以确切了解问题首次出现时更改了哪些代码。


谢谢您的回答。我确实删除了一半,甚至从项目中排除了我的主要 .js 文件。不知何故,错误仍然发生。这就是为什么我对此感到如此沮丧。是的,我正在使用 git。我今天才意识到这个错误。自从这成为小组项目以来,已经有很多提交。可能会进行深入检查。再次感谢您的想法。
@procatmer 使用相同的策略来查找 git 提交。例如,如果我有 10 次提交(A、B、C、D、E、F、G、H、I、J),其中 A 是最旧的,我会 git checkout E 来查看问题是否已经存在。如果是,我将继续在提交的前半部分寻找问题。否则,我在下半场寻找问题。
@procatmer 另外,如果您省略了主 .js 文件并且问题仍然存在......它可能是您通过 <script src="..."> 标签引入的库!也许有些事情不值得担心(特别是因为它只是一个警告)?
我终于找到了问题所在。我用你的第二个想法来跟踪变化。是的,问题来自外部 .js 文件。显然,这很重要。它大大减慢了我的网站。无论如何,再次感谢您的回答和想法。
您可以使用 git bisect 来应用二进制搜索。我认为这只是为了发现错误。
R
ReinstateMonica3167040

我在我的代码中找到了这条消息的根,它搜索并隐藏或显示了节点(离线)。这是我的代码:

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

https://i.stack.imgur.com/SbUaa.png

现在:

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

https://i.stack.imgur.com/XDy3z.png

而且我觉得现在搜索速度更快(229 个节点)。


总而言之,通过接收违规,您可以优化您的代码,并且现在它的性能更好。
M
Matt Leonowicz

为了确定问题的根源,运行您的应用程序,并将其记录在 Chrome 的性能选项卡中。

在那里您可以检查需要很长时间才能运行的各种功能。就我而言,与控制台中的警告相关的文件来自 AdBlock 扩展加载的文件,但在您的情况下,这可能是其他内容。

检查这些文件并尝试确定这是某个扩展程序的代码还是您的代码。 (如果是你的,那么你已经找到了问题的根源。)


不,我没有 AdBlock,我仍然可以在控制台中找到它。
尝试使用性能选项卡对其进行分析,并寻找长时间运行的功能的来源。这可以是任何东西,但这是确定问题根源的一种潜在方法。
J
Jordan Reddick

查看网络选项卡下的 Chrome 控制台,找到加载时间最长的脚本。

就我而言,有一组 Angular add on 脚本,我已包含但尚未在应用程序中使用:

<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 文件。

所有这些文件都在我的其他网站上运行,没有产生任何错误,但是我在一个几乎没有任何功能的新网络应用程序上遇到了这个“长时间运行任务”错误。删除后错误立即停止。

我最好的猜测是,这些 Angular 插件正在递归地查看 DOM 中越来越深的部分以获取它们的开始标签——没有找到,它们必须在退出之前遍历整个 DOM,这比 Chrome 预期的要长——因此发出了警告。


w
wf9a5m75

我在 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
});

插入此技巧代码后,所有警告消息都消失了。


J
JimiSweden

在此添加我的见解,因为该线程是有关该主题的“转到”stackoverflow 问题。

我的问题出在 Material-UI 应用程序中(早期阶段)

放置自定义主题提供程序是原因

当我进行一些计算强制渲染页面时(一个组件,“显示结果”,取决于其他组件中的设置,“输入部分”)。

一切都很好,直到我更新了强制“结果组件”重新呈现的“状态”。这里的主要问题是我在与“结果组件”SummaryAppBarPure 相同的渲染器(App.js / return.. )中有一个 material-ui 主题(https://material-ui.com/customization/theming/#a-note-on-performance

解决方案是将 ThemeProvider 提升一级(Index.js),并在此处包装 App 组件,因此不会强制 ThemeProvider 重新计算和绘制/布局/重排。

在 App.js 中:

  return (
    <>
      <MyThemeProvider>
      <Container className={classes.appMaxWidth}>

        <SummaryAppBarPure
//...

在 index.js 中

ReactDOM.render(
  <React.StrictMode>
      <App />
//...

在 App.js 中:

return (
    <>
      {/* move theme to index. made reflow problem go away */}
      {/* <MyThemeProvider> */}
      <Container className={classes.appMaxWidth}>

        <SummaryAppBarPure
//...

在 index.js 中

ReactDOM.render(
  <React.StrictMode>
    <MyThemeProvider>
      <App />
//...

R
ReinstateMonica3167040

这是在 Chrome 56 测试版中添加的,即使它不在 Chromium 博客的此更改日志中:Chrome 56 Beta: “Not Secure” warning, Web Bluetooth, and CSS position: sticky

您可以使用隐藏违规复选框将其隐藏在控制台的过滤器栏中。


P
Paul-Sebastian

这是来自 Google Chrome 的违规错误,显示 Verbose 日志记录级别何时启用。

错误信息示例:

https://i.stack.imgur.com/C1Aoj.png

解释:

Reflow 是 Web 浏览器进程的名称,用于重新计算文档中元素的位置和几何形状,以重新渲染部分或全部文档。因为重排是浏览器中的一种用户阻塞操作,所以对于开发人员了解如何提高重排时间以及了解各种文档属性(DOM 深度、CSS 规则效率、不同类型的样式更改)对重排的影响很有帮助时间。有时重排文档中的单个元素可能需要重排其父元素以及跟随它的任何元素。

原创文章:Minimizing browser reflow,用户体验开发人员 Lindsey Simon 发表在 developers.google.com 上。

this is the link Google Chrome 会在性能分析器中的布局配置文件(淡紫色区域)中为您提供有关警告的更多信息。


n
noetix

如果您使用的是 Chrome Canary(或 Beta),只需选中“隐藏违规”选项即可。

https://i.stack.imgur.com/1u1GJ.jpg


J
Jens

对于它的价值,这是我遇到的 2 美分

[Violation] Forced reflow while executing JavaScript took <N>ms

警告。有问题的页面是从用户内容生成的,所以我对 DOM 的大小并没有太大的影响。就我而言,问题是一个包含两列的表,可能有数百甚至数千行。 (还没有实现按需行加载,抱歉!)

使用 jQuery,页面在 keydown 上选择一组行并切换它们的可见性。我注意到在该集合上使用 toggle() 比使用 hide() & 更容易触发警告。 show() 明确。

有关此特定性能方案的更多详细信息,另请参阅 this article


R
ReinstateMonica3167040

当您在执行结束之前多次调用函数时,通常会发生强制回流。

例如,您可能在智能手机上遇到问题,但在经典浏览器上却没有。

我建议使用 setTimeout 来解决问题。

这不是很重要,但我再说一遍,当您多次调用函数时会出现问题,而不是当函数花费超过 50 毫秒时。我认为你的答案是错误的。

关闭 1-by-1 调用并重新加载代码以查看它是否仍然产生错误。如果第二个脚本导致错误,请根据违规的持续时间使用 setTimeOut。


这不是解决方案。这是一个建议,最好将其作为对原始问题的评论。
G
Gerdixx

这不是一个错误,只是一个简单的消息。要执行此消息,请将
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">(示例)
更改为
<!DOCTYPE html>(Firefox 源期望此)

该消息在 Google Chrome 74 和 Opera 60 中显示。改了之后就很清楚了,0冗长。
解决办法


只是一些建议:您的答案与问题无关。修复您的答案或将其删除。问题是“为什么 Chrome 浏览器控制台显示违规警告”。答案是它是较新的 Chrome 浏览器中的一项功能,如果网页在执行 JS 时导致浏览器过度回流,它会提醒您。有关详细信息,请参阅 this resource from Google