大约两个月前,我们开始使用Rollbar来通知我们Web应用程序中的各种错误。从那以后,我们偶尔会遇到一些错误:

超出ResizeObserver循环限制

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

奥蕾莉亚调整大小

但它似乎也没有使用ResizeObserver。

同样令人困惑的是,这些错误消息从1月份就开始出现,但ResizeObserver支持最近才添加到Chrome 65。

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

Chrome: 63.0.3239 (ResizeObserver循环限制超过) Chrome: 64.0.3282 (ResizeObserver循环限制超过) Edge: 14.14393 (SecurityError) Edge: 15.15063 (SecurityError)

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


当前回答

在我的情况下,问题“ResizeObserver -循环限制超出”是由于窗口触发的。addEventListener("resize"和React的React. usestate . addEventListener。

详细地说,我正在处理名为useWindowResize的钩子,用例是这样的const [windowWidth, windowHeight] = useWindowResize();

代码通过useEffect对windowWidth/windowHeight的变化做出反应。

React.useEffect(() => {
    ViewportService.dynamicDimensionControlledBy(
        "height",
        { windowWidth, windowHeight },
        widgetModalRef.current,
        { bottom: chartTitleHeight },
        false,
        ({ h }) => setWidgetHeight(h),
    );
}, [windowWidth, windowHeight, widgetModalRef, chartTitleHeight]);

所以任何浏览器窗口大小的调整都会导致这个问题。

我发现由于连接旧javascript世界(DOM操作,浏览器的事件)和新javascript世界(React)引起的许多类似问题可以通过setTimeout解决,但我将避免它,并在可能的情况下将其称为反模式。

因此,我的解决方案是将setter方法包装到setTimeout函数中。

React.useEffect(() => {
    ViewportService.dynamicDimensionControlledBy(
        "height",
        { windowWidth, windowHeight },
        widgetModalRef.current,
        { bottom: chartTitleHeight },
        false,
        ({ h }) => setTimeout(() => setWidgetHeight(h), 0),
    );
}, [windowWidth, windowHeight, widgetModalRef, chartTitleHeight]);

其他回答

https://github1s.com/chromium/chromium/blob/master/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc#L44-L45 https://github1s.com/chromium/chromium/blob/master/third_party/blink/renderer/core/frame/local_frame_view.cc#L2211-L2212

在查看源代码后,在我的案例中,问题似乎是在调用NotifyResizeObservers函数时出现的,并且没有注册的观察者。

GatherObservations函数将返回min_depth为4096,在没有观察者的情况下,在这种情况下,我们将得到“ResizeObserver循环limit exceeded”错误。

我解决这个问题的方法是在页面的整个生命周期中设置一个观察者。

我遇到了柏树测试无法运行的问题。 我发现,正确的方法不是处理异常,而是编辑tsconfig。Json,目标是新的es6版本,如下所示:

{ “扩展”:“. . / tsconfig.json”, " compilerOptions ": { “baseUrl”:“. . / node_modules”, "target": "es5",——> old "target": "es6",——> new "types": ["cypress", "@testing-library/cypress"], “sourceMap”:真的 }, “包括”:( “* * / * .ts” ] }

赛普拉斯的一线解决方案。编辑文件support/commands.js:

Cypress.on(
  'uncaught:exception',
  (err) => !err.message.includes('ResizeObserver loop limit exceeded')
);

设法解决这个问题,在React为我们的错误记录器设置。

观察者错误传播到窗口。Onerror错误处理程序,因此通过存储原始窗口。Onerror,然后你可以用一个自定义方法替换它,该方法不会抛出这个特定的错误。其他错误被允许正常传播。

确保在useEffect清理中重新连接原来的onerror。

const defaultOnErrorFn = useRef(window.onerror);

useEffect(() => {
  window.onerror = (...args) => {
    if (args[0] === 'ResizeObserver loop limit exceeded') {
      return true;
    } else {
      defaultOnErrorFn.current && defaultOnErrorFn.current(...args);
    }
  };
  return () => {
    window.onerror = defaultOnErrorFn.current;
  };
}, []);

您可以安全地忽略这个错误。

一个规范的作者在评论中对你的问题写了一个评论,但它不是一个答案,在评论中不清楚答案是否真的是这个线程中最重要的一个,并且是一个让我在我们的哨兵日志中很舒服地忽略它的答案。

This错误意味着ResizeObserver不能在一个动画帧中传递所有的观察结果。它是良性的(您的站点不会崩溃)。——Aleksandar Totic 4月15日3:14

在规范存储库中也存在一些与此相关的问题。