ResizeObserver - 超出了循环限制

IOI*_*OIO 43 google-chrome aurelia microsoft-edge rollbar

大约两个月前,我们开始使用Rollbar通知我们Web应用程序中的各种错误.从那时起,我们偶尔会遇到错误:

ResizeObserver loop limit exceeded

令我困惑的是我们没有使用ResizeObserver,我调查了唯一一个我认为可能是罪魁祸首的插件,即:

Aurelia Resize

但它似乎也没有使用ResizeObserver.

令人困惑的是,这些错误消息自1月以来一直在发生,但ResizeObserver最近才向Chrome 65添加了支持.

给我们这个错误的浏览器版本是:

  • Chrome:63.0.3239(超出ResizeObserver循环限制)
  • Chrome:64.0.3282(超出ResizeObserver循环限制)
  • 边缘:14.14393(SecurityError)
  • 边缘:15.15063(SecurityError)

所以我想知道这是否可能是一个浏览器错误?或者可能是一个与实际无关的错误ResizeObserver

Jac*_*ask 66

您可以放心地忽略此错误.

其中一位规范作者在对你的问题的评论中写道,但它不是一个答案,并且在评论中不清楚答案是这个帖子中最重要的答案,而且让我很乐意忽略它我们的哨兵记录.

此错误表示ResizeObserver无法在单个动画帧中传递所有观察结果.这是良性的(您的网站不会破坏).- Aleksandar Totic 4月15日3:14

规范库中也存在一些相关问题.

  • 为了帮助任何人理解为什么他们会看到这个错误,我创建了一个包含一堆不同的简化测试用例的存储库,您可能会在其中遇到此错误:https://github.com/OliverJAsh/resize-observer-loop-tests (7认同)
  • 我们遇到这个问题来自“@microsoft/applicationinsights-web”,它负责记录我们的客户端错误。因此,我们只需在 applicationInsights 之前设置错误事件处理程序并调用“stopImmediatePropagation”和“preventDefault”来忽略此错误 (3认同)
  • 另请参阅[视频控件存在时触发错误“ResizeObserver 循环限制超出”](https://crbug.com/809574)。 (2认同)
  • 我不确定忽略此错误总是明智/安全的。它可以指示性能问题,例如:https://jsbin.com/cadafaduwu/1/edit?html,css,js,console,output。调整大小观察者回调会触发元素再次调整大小,从而创建一个循环。发生这种情况时,通常是一个错误 - 您不想从调整大小观察者回调触发另一个调整大小。 (2认同)

Ran*_*ani 53

这是一个老问题,但它仍然可能对某人有帮助。您可以通过将回调包装在requestAnimationFrame. 例如:

const resizeObserver = new ResizeObserver(entries => {
   // We wrap it in requestAnimationFrame to avoid this error - ResizeObserver loop limit exceeded
   window.requestAnimationFrame(() => {
     if (!Array.isArray(entries) || !entries.length) {
       return;
     }
     // your code
   });
});
Run Code Online (Sandbox Code Playgroud)

  • 需要什么条件?"!Array.isArray(entries) || !entries.length" (4认同)
  • 您可能不想这样做。“您可以将执行限制为单个帧”更准确的解释是您实际上将布局更改推送到宏任务队列上。不幸的是,这是一个重要的区别,因为 RO 通常会在布局和绘制之间运行。这很重要,因为它可以让您在没有“卡顿”或“闪烁”的情况下进行布局更改您可以在这里找到一个很好的示例:https://github.com/petyosi/react-virtuoso/issues/269 这并不意味着您不能使用此解决方案 - 但如果您使用 RO 进行同步更新,请重新考虑。 (4认同)
  • 你怎么知道要这样做......? (2认同)
  • @ADJenks 来自上面的响应:“此错误意味着 ResizeObserver 无法在单个动画帧内提供所有观察结果”。通过将其包装在 requestAnimationFrame 中,您可以将执行限制为单个帧 (2认同)

Kha*_*321 22

如果您正在使用 Cypress 并且遇到此问题,您可以在 Cypress 中使用 support/index.js 或 commands.ts 中的以下代码安全地忽略它

const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on('uncaught:exception', (err) => {
    /* returning false here prevents Cypress from failing the test */
    if (resizeObserverLoopErrRe.test(err.message)) {
        return false
    }
})
Run Code Online (Sandbox Code Playgroud)

您可以在此处关注有关它的讨论。由于赛普拉斯维护者自己提出了这个解决方案,所以我相信这样做是安全的。

  • 您的正则表达式并不完全符合您的预期。方括号包含一个字符类,其中的 ^ 对其进行否定,因此实际上您会忽略以句子中包含的任何字符开头的任何错误。如果您想使用正则表达式,则负向前瞻就是您要寻找的:`return /^(?!ResizeObserver 超出循环限制)/.test(err.message)` 应该没问题。尽管 `err.message.startsWith('ResizeObserver 循环限制超出')` 可能更容易。 (7认同)
  • 我什至会说正则表达式是不必要的——您只需在错误消息中查找字符串“ResizeObserver 超出循环限制”即可,简单明了。 (5认同)
  • 我可以确认 `if (err.message.includes("ResizeObserver 循环限制超出"))` 与正则表达式一样有效。 (4认同)

小智 10

对于摩卡用户:

下面的代码片段覆盖了 mocha 安装的 window.onerror 挂钩,并将错误转换为警告。 https://github.com/mochajs/mocha/blob/667e9a21c10649185e92b319006cea5eb8d61f31/browser-entry.js#L74

// ignore ResizeObserver loop limit exceeded
// this is ok in several scenarios according to 
// https://github.com/WICG/resize-observer/issues/38
before(() => {
  // called before any tests are run
  const e = window.onerror;
  window.onerror = function(err) {
    if(err === 'ResizeObserver loop limit exceeded') {
      console.warn('Ignored: ResizeObserver loop limit exceeded');
      return false;
    } else {
      return e(...arguments);
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

不确定是否有更好的方法..


vas*_*kch 9

该错误可能值得调查。它可以表明代码中存在可以修复的问题。

\n

在我们的例子中,观察到的元素大小调整触发了页面上的更改,这导致了第一个元素再次调整大小,这再次触发了页面上的更改,这再次导致了第一个元素 \xe2\x80\ 的大小调整xa6 你知道这一切如何结束。

\n

本质上,我们创建了一个无限循环,显然无法适合单个动画帧。我们通过使用保留页面上的更改来打破它setTimeout()(尽管这并不完美,因为它可能会导致用户出现一些闪烁)。

\n

因此,现在每次ResizeObserver loop limit exceeded出现在我们的哨兵中,我们都会将其视为有用的提示,并尝试找出问题的原因。

\n

  • 谢谢你的回答。这是我们的情况,我们让图像观察者和观察者尝试向服务器发送请求以获取新的图像衍生物,但服务器以 404 响应,并且 Opera/Chrome 添加默认图标来指示损坏的图像。这个图标触发了一个新的观察者调用,因为图像的大小发生了变化,我们再次通过设置 image.src 来重置图像,这会导致无限的进程。这里有一些更多细节 https://dgo.to/easy_responsive_images/3285476 我们案例中的解决方案是检查观察到的图像大小以检测该图像是否不是默认的损坏图像图标。 (2认同)

小智 6

我们有同样的问题。我们发现 chrome 扩展是罪魁祸首。具体来说,Loom chrome 扩展导致了错误(或者我们的代码与 Loom 扩展的一些交互)。当我们禁用扩展程序时,我们的应用程序工作。

我建议禁用某些扩展/插件以查看其中一个是否可能导致错误。

  • 或者只是在隐身模式下查看。大多数人可能在隐身模式下没有启用或启用很少的扩展程序。 (3认同)

Kre*_*eja 6

添加去抖就像

新的 ResizeObserver(_.debounce(entries => {}, 200);

为我修正了这个错误