js 使用 ResizeObserver 时报错,代码实现逻辑如下:
function observeVideoDom (width: number, height: number) {const videoDom = document.getElementById('videoDom')if (!videoDom) returnif (window.ResizeObserver) {// ResizeObserver 在 iOS13.4及以上,安卓 4.4.5及以上才支持,如果不支持用轮询判断const resizeObserver = new ResizeObserver(() => {videoSizeReset(width, height)})resizeObserver.observe(videoDom)} else {let previousWidth = videoDom.clientWidthlet previousHeight = videoDom.clientHeightconst checkSize = () => {const currentWidth = videoDom.clientWidthconst currentHeight = videoDom.clientHeightif (currentWidth !== previousWidth || currentHeight !== previousHeight) {videoSizeReset(width, height)previousWidth = currentWidthpreviousHeight = currentHeight}}const scheduleCheck = () => {checkSize()requestAnimationFrame(scheduleCheck)}requestAnimationFrame(scheduleCheck)}}
主要功能是监测 videoDom 元素的盒子大小变化后,重新赋值videoDom 元素的盒子大小,由于重新赋值的操作会再次改变 videoDom 元素的盒子大小,会导致报错了 ResizeObserver loop completed with undelivered notifications.
解决方案,给 ResizeObserver 的回调函数加 防抖或者 requestAnimationFrame
改后如下:
function observeVideoNativeDom (width: number, height: number) {const videoNativeDom = document.getElementById('video-native')if (!videoNativeDom) returnif (window.ResizeObserver) {// ResizeObserver 在 iOS13.4及以上,安卓 4.4.5及以上才支持,如果不支持用轮询判断const resizeObserver = new ResizeObserver(debounce(() => {videoSizeReset(width, height)}))resizeObserver.observe(videoNativeDom)} else {let previousWidth = videoNativeDom.clientWidthlet previousHeight = videoNativeDom.clientHeightconst checkSize = () => {const currentWidth = videoNativeDom.clientWidthconst currentHeight = videoNativeDom.clientHeightif (currentWidth !== previousWidth || currentHeight !== previousHeight) {videoSizeReset(width, height)previousWidth = currentWidthpreviousHeight = currentHeight}}const scheduleCheck = () => {checkSize()requestAnimationFrame(scheduleCheck)}requestAnimationFrame(scheduleCheck)}} // 或者