From 76e40eed35171092ff8a3ea15b1f8faf9c872112 Mon Sep 17 00:00:00 2001 From: WilliamKoza Date: Fri, 25 Jan 2019 15:59:55 +0100 Subject: [PATCH] feat(docs-infra): add debouncing in storing scroll position (#28368) There is no debouncing when we store the scroll Position. Currently, we have a message in the console after a while: >Throttling history state changes to prevent the browser from hanging see: https://bugs.chromium.org/p/chromium/issues/detail?id=786211 for more informations PR Close #28368 --- aio/src/app/app.component.spec.ts | 7 ------- aio/src/app/app.component.ts | 3 --- aio/src/app/shared/scroll.service.spec.ts | 21 ++++++++++++++++----- aio/src/app/shared/scroll.service.ts | 4 ++++ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/aio/src/app/app.component.spec.ts b/aio/src/app/app.component.spec.ts index a3313e3f2b..3c8f6b76a6 100644 --- a/aio/src/app/app.component.spec.ts +++ b/aio/src/app/app.component.spec.ts @@ -169,13 +169,6 @@ describe('AppComponent', () => { expect(component.tocMaxHeight).toMatch(/^\d+\.\d{2}$/); }); - - it('should update `scrollService.updateScrollPositonInHistory()`', () => { - const scrollService = fixture.debugElement.injector.get(ScrollService); - spyOn(scrollService, 'updateScrollPositionInHistory'); - component.onScroll(); - expect(scrollService.updateScrollPositionInHistory).toHaveBeenCalled(); - }); }); describe('SideNav', () => { diff --git a/aio/src/app/app.component.ts b/aio/src/app/app.component.ts index d7d37cf0d6..1fad31d792 100644 --- a/aio/src/app/app.component.ts +++ b/aio/src/app/app.component.ts @@ -339,9 +339,6 @@ export class AppComponent implements OnInit { // Dynamically change height of table of contents container @HostListener('window:scroll') onScroll() { - - this.scrollService.updateScrollPositionInHistory(); - if (!this.tocMaxHeightOffset) { // Must wait until `mat-toolbar` is measurable. const el = this.hostElement.nativeElement as Element; diff --git a/aio/src/app/shared/scroll.service.spec.ts b/aio/src/app/shared/scroll.service.spec.ts index fff5c0ea7b..5e0f72bb8a 100644 --- a/aio/src/app/shared/scroll.service.spec.ts +++ b/aio/src/app/shared/scroll.service.spec.ts @@ -34,11 +34,6 @@ describe('ScrollService', () => { 'viewportScroller', ['getScrollPosition', 'scrollToPosition']); - - beforeEach(() => { - spyOn(window, 'scrollBy'); - }); - beforeEach(() => { injector = ReflectiveInjector.resolveAndCreate([ ScrollService, @@ -52,8 +47,24 @@ describe('ScrollService', () => { document = injector.get(DOCUMENT); scrollService = injector.get(ScrollService); location = injector.get(Location); + + spyOn(window, 'scrollBy'); }); + it('should debounce `updateScrollPositonInHistory()` after 500ms', fakeAsync(() => { + const updateScrollPositionInHistorySpy = spyOn(scrollService, 'updateScrollPositionInHistory'); + + window.dispatchEvent(new Event('scroll')); + tick(249); + window.dispatchEvent(new Event('scroll')); + tick(249); + window.dispatchEvent(new Event('scroll')); + tick(249); + expect(updateScrollPositionInHistorySpy).not.toHaveBeenCalled(); + tick(1); + expect(updateScrollPositionInHistorySpy).toHaveBeenCalledTimes(1); + })); + it('should set `scrollRestoration` to `manual` if supported', () => { if (scrollService.supportManualScrollRestoration) { expect(window.history.scrollRestoration).toBe('manual'); diff --git a/aio/src/app/shared/scroll.service.ts b/aio/src/app/shared/scroll.service.ts index 4478ead0a7..d6086266f4 100644 --- a/aio/src/app/shared/scroll.service.ts +++ b/aio/src/app/shared/scroll.service.ts @@ -2,6 +2,7 @@ import { Injectable, Inject } from '@angular/core'; import { Location, PlatformLocation, ViewportScroller } from '@angular/common'; import { DOCUMENT } from '@angular/common'; import { fromEvent } from 'rxjs'; +import { debounceTime } from 'rxjs/operators'; export const topMargin = 16; /** @@ -45,6 +46,9 @@ export class ScrollService { // On resize, the toolbar might change height, so "invalidate" the top offset. fromEvent(window, 'resize').subscribe(() => this._topOffset = null); + fromEvent(window, 'scroll') + .pipe(debounceTime(250)).subscribe(() => this.updateScrollPositionInHistory()); + try { this.supportManualScrollRestoration = !!window && !!window.scrollTo && 'scrollX' in window && 'scrollY' in window && !!history && !!history.scrollRestoration;