Skip to content

Commit

Permalink
fix(image): cleanup unobserve
Browse files Browse the repository at this point in the history
  • Loading branch information
07akioni committed Jun 19, 2022
1 parent 226a8d9 commit 32cf3be
Showing 1 changed file with 37 additions and 22 deletions.
59 changes: 37 additions & 22 deletions src/image/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ export const resolveOptionsAndHash = (
}
}

// root -> options -> [observer, elements]
const observers = new WeakMap<
Document | Element,
Map<string, [IntersectionObserver, number]>
Map<string, [IntersectionObserver, Set<Element | Document>]>
>()

export const observeIntersection: (
Expand All @@ -38,48 +39,62 @@ export const observeIntersection: (
) => () => void = (el, options) => {
if (!el) return () => {}
const resolvedOptionsAndHash = resolveOptionsAndHash(options)
let rootObservers: Map<string, [IntersectionObserver, number]>
const _rootObservers = observers.get(resolvedOptionsAndHash.options.root)
const { root } = resolvedOptionsAndHash.options
let rootObservers: Map<
string,
[IntersectionObserver, Set<Element | Document>]
>
const _rootObservers = observers.get(root)
if (_rootObservers) {
rootObservers = _rootObservers
} else {
rootObservers = new Map()
observers.set(resolvedOptionsAndHash.options.root, rootObservers)
observers.set(root, rootObservers)
}
let observer: IntersectionObserver
let observerAndObservedElements: [
IntersectionObserver,
Set<Element | Document>
]
if (rootObservers.has(resolvedOptionsAndHash.hash)) {
const observerAndObservedElementCount =
observerAndObservedElements =
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
rootObservers.get(resolvedOptionsAndHash.hash)!
observer = observerAndObservedElementCount[0]
observerAndObservedElementCount[1]++
if (!observerAndObservedElements[1].has(el)) {
observer = observerAndObservedElements[0]
observerAndObservedElements[1].add(el)
observer.observe(el)
}
} else {
observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
unobserve()
const img = entry.target as HTMLImageElement
if (!img.src) {
img.src = img.dataset.src || ''
}
}
})
})
rootObservers.set(resolvedOptionsAndHash.hash, [observer, 1])
observer.observe(el)
observerAndObservedElements = [observer, new Set([el])]
rootObservers.set(resolvedOptionsAndHash.hash, observerAndObservedElements)
}
observer.observe(el)
return () => {
const observerAndObservedElementCount = rootObservers.get(
resolvedOptionsAndHash.hash
)
if (observerAndObservedElementCount) {
observerAndObservedElementCount[0].unobserve(el)
observerAndObservedElementCount[1]--
if (observerAndObservedElementCount[1] <= 0) {
rootObservers.delete(resolvedOptionsAndHash.hash)
}
if (!rootObservers.size) {
observers.delete(resolvedOptionsAndHash.options.root)
}
let unobservered = false
const unobserve = (): void => {
if (unobservered) return
unobservered = true
if (observerAndObservedElements[1].has(el)) {
observerAndObservedElements[0].unobserve(el)
observerAndObservedElements[1].delete(el)
}
if (observerAndObservedElements[1].size <= 0) {
rootObservers.delete(resolvedOptionsAndHash.hash)
}
if (!rootObservers.size) {
observers.delete(root)
}
}
return unobserve
}

0 comments on commit 32cf3be

Please sign in to comment.