JavaScript
js/listener-cleanup
Listeners, timers and observers a view starts are removed when it goes away; one AbortController signal can end them all.
moderatemanualfe-javascript
Why
In a single-page app, a view that adds a resize listener, a setInterval or an IntersectionObserver and never removes it keeps running after navigation: memory grows, handlers fire twice after the view comes back, and they act on elements that no longer exist.
Fix
Create one AbortController per view or component, pass { signal } to every addEventListener and to fetch, and call abort() on teardown (the effect cleanup, onUnmounted, disconnectedCallback, DestroyRef.onDestroy). Clear timers with clearInterval and call disconnect() on observers in the same place.
Examples
// bad
connectedCallback() { window.addEventListener('resize', this.layout) }
// good
connectedCallback() {
this.controller = new AbortController()
window.addEventListener('resize', this.layout, { signal: this.controller.signal })
}
disconnectedCallback() { this.controller.abort() }Sources
Facts
- Id
js/listener-cleanup- Severity
- moderate
- Check
- manual a person reviews it; the report lists it as a checklist
- Applies to
jsxvuesvelteastrohtml- Taught by the skill
fe-javascriptJavaScript in the browser- Since version
- 0.1.0
Read it in the terminal
npx github:dawidolko/frontend-skills explain js/listener-cleanup