thoun / bga-zoom

5 stars 1 forks source link

When resizing the window, error "ResizeObserver loop completed with undelivered notifications." #3

Open TTransmit opened 1 year ago

TTransmit commented 1 year ago

When I resize the browser window, I very frequently (at least every 10 seconds when dragging window width left and right) see the error:

Javascript error:
ResizeObserver loop completed with undelivered notifications.
Script: https://studio.boardgamearena.com/1/reefencounter?table=539693
Url: https://studio.boardgamearena.com/1/reefencounter?table=539693
BGA version 231123-1002
U=2361652
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36

As a minimal test, I tried following the instructions in the README.md of this project precisely in a new project in studio.boardgamearena.com . The only change was to add <div id ="game-table">Hello</div> below the line in the .tpl file This is your game interface. You can edit this HTML in your ".tpl" file. It has the same issue.

It should be possible to try the minimal version here: https://studio.boardgamearena.com/lobby?game=9397

My initial guess was that something is going wrong with the throttle. Logging to console within the throttle didn't show an obvious error, it looks like the throttle is working. I've tried playing around with the code with no luck. I was thinking it may be to do with the automatic zooming of BGA. Perhaps something like that is triggering the resizeObserver that hasn't been throttled so the ResizeObserver thinks there is an infinite loop? I tried various instructions to turn BGA zooming off but it seems that the error persists. I looked at the Heat, Glow and King of Tokyo code bases and couldn't find something obviously different (though those code bases are using TypeScript, which I haven't tried).

It happens on Chrome and Firefox on MacOS.

TTransmit commented 1 year ago

Three minimal changes that stop the error being thrown and seem to still give the expected behaviour:

  1. Comment out the ResizeObserver creation at https://github.com/thoun/bga-zoom/blob/1.0.2/bga-zoom.js#L112 new ResizeObserver(advThrottle(function () { return _this.zoomOrDimensionChanged(); }, this.throttleTime, { leading: true, trailing: true, })).observe(settings.element);
  2. Use the same throttle for the EventListener('resize' and the ResizeObserver without triggering setAutoZoom. Replace https://github.com/thoun/bga-zoom/blob/1.0.2/bga-zoom.js#L104-L113 with:
        this.throttleZoomOrDimenChanged = advThrottle(function () { return _this.zoomOrDimensionChanged(); }, this.throttleTime, { leading: true, trailing: true, });
        window.addEventListener('resize', this.throttleZoomOrDimenChanged);
        if (window.ResizeObserver) {
            new ResizeObserver(this.throttleZoomOrDimenChanged).observe(settings.element);
        }
  3. Use the same throttle for the EventListener('resize' and the ResizeObserver with triggering setAutoZoom but also comment out else { this.setZoom(newZoom) } at the end of the ZoomManager.prototype.setAutoZoom function. https://github.com/thoun/bga-zoom/blob/1.0.2/bga-zoom.js#L157 Commenting out else { this.setZoom(newZoom) } is only required if autoZoom with expectedWidth is set when creating the ZoomManager. Replace https://github.com/thoun/bga-zoom/blob/1.0.2/bga-zoom.js#L104-L113 with:
        this.throttledZoomOrDimenChanged = advThrottle(function () {
            var _a;
            _this.zoomOrDimensionChanged();
            if ((_a = _this.settings.autoZoom) === null || _a === void 0 ? void 0 : _a.expectedWidth) {
                _this.setAutoZoom();
            }
        }, this.throttleTime, { leading: true, trailing: true, });
        window.addEventListener('resize', this.throttledZoomOrDimenChanged);
        if (window.ResizeObserver) {
            new ResizeObserver(this.throttledZoomOrDimenChanged).observe(settings.element);
        }

It's not clear to me what all of these lines do. They look designed to support different browsers. So these changes may cause issues in some browsers.

It seems that EventListener('resize' and the ResizeObserver can trigger each other. setZoom in setAutoZoom may also trigger the ResizeObserver.

I need to investigate why other games using the same code don't throw the same error.