大约两个月前,我们开始使用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无关的错误?


当前回答

这个错误可能值得调查一下。它可以指出代码中可以修复的问题。

在我们的例子中,观察到的一个元素的大小调整引发了页面上的变化,这又导致了第一个元素的大小调整,这又触发了页面上的变化,这又导致了第一个元素的大小调整,……你知道这是如何结束的。

从本质上讲,我们创建了一个无法装入单个动画帧的无限循环。我们通过使用setTimeout()在页面上保持更改来打破它(尽管这并不完美,因为它可能会对用户造成一些闪烁)。

因此,每当ResizeObserver循环限制超出我们的哨兵,我们把它视为一个有用的提示,并试图找到问题的原因。

其他回答

添加debounce

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

为我修正了这个错误

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”错误。

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

设法解决这个问题,在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;
  };
}, []);

这个错误可能值得调查一下。它可以指出代码中可以修复的问题。

在我们的例子中,观察到的一个元素的大小调整引发了页面上的变化,这又导致了第一个元素的大小调整,这又触发了页面上的变化,这又导致了第一个元素的大小调整,……你知道这是如何结束的。

从本质上讲,我们创建了一个无法装入单个动画帧的无限循环。我们通过使用setTimeout()在页面上保持更改来打破它(尽管这并不完美,因为它可能会对用户造成一些闪烁)。

因此,每当ResizeObserver循环限制超出我们的哨兵,我们把它视为一个有用的提示,并试图找到问题的原因。

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

const resizeObserverLoopErrRe = /^[^(ResizeObserver循环限制超过)]/ 柏树。On ('uncaught:exception', (err) => { /*在这里返回false可以防止Cypress测试失败*/ if (resizeObserverLoopErrRe.test(err.message)) { 返回假 } })

你可以在这里跟随关于它的讨论。 由于Cypress维护者自己提出了这个解决方案,所以我相信这样做是安全的。