1717import { bindReporter } from './lib/bindReporter' ;
1818import { getActivationStart } from './lib/getActivationStart' ;
1919import { getVisibilityWatcher } from './lib/getVisibilityWatcher' ;
20- import { addPageListener , removePageListener } from './lib/globalListeners' ;
20+ import { addPageListener } from './lib/globalListeners' ;
2121import { initMetric } from './lib/initMetric' ;
2222import { initUnique } from './lib/initUnique' ;
2323import { LCPEntryManager } from './lib/LCPEntryManager' ;
@@ -80,12 +80,16 @@ export const onLCP = (onReport: (metric: LCPMetric) => void, opts: ReportOpts =
8080 if ( po ) {
8181 report = bindReporter ( onReport , metric , LCPThresholds , opts . reportAllChanges ) ;
8282
83+ // Uses an AbortController to cancel all event listeners whenever one of them is triggered.
84+ const controller = new AbortController ( ) ;
85+
8386 // Ensure this logic only runs once, since it can be triggered from
8487 // any of three different event listeners below.
8588 const stopListening = runOnce ( ( ) => {
8689 handleEntries ( po . takeRecords ( ) as LCPMetric [ 'entries' ] ) ;
8790 po . disconnect ( ) ;
8891 report ( true ) ;
92+ controller . abort ( ) ;
8993 } ) ;
9094
9195 // Need a separate wrapper to ensure the `runOnce` function above is
@@ -96,9 +100,6 @@ export const onLCP = (onReport: (metric: LCPMetric) => void, opts: ReportOpts =
96100 // task to reduce potential INP impact.
97101 // https://github.com/GoogleChrome/web-vitals/issues/383
98102 whenIdleOrHidden ( stopListening ) ;
99- removePageListener ( event . type , stopListeningWrapper , {
100- capture : true ,
101- } ) ;
102103 }
103104 } ;
104105
@@ -109,6 +110,11 @@ export const onLCP = (onReport: (metric: LCPMetric) => void, opts: ReportOpts =
109110 for ( const type of [ 'keydown' , 'click' , 'visibilitychange' ] ) {
110111 addPageListener ( type , stopListeningWrapper , {
111112 capture : true ,
113+ // Effectively removes all event listeners when the controller is aborted
114+ // This is supported in all browsers as of Sept 2021
115+ // For older or non-compliant browsers, we fall back to using the once: true option
116+ signal : controller . signal ,
117+ once : true ,
112118 } ) ;
113119 }
114120 }
0 commit comments