Skip to content

Commit

Permalink
fix(useScript): singleton abort promise
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Oct 14, 2024
1 parent 8fd2a67 commit 7a026f4
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 10 deletions.
6 changes: 5 additions & 1 deletion packages/schema/src/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ export interface ScriptInstance<T extends BaseScriptApi> {
/**
* @internal
*/
_triggerAbortController?: AbortController
_triggerAbortController?: AbortController | null
/**
* @internal
*/
_triggerAbortPromise?: Promise<void>
/**
* @internal
*/
Expand Down
32 changes: 23 additions & 9 deletions packages/unhead/src/composables/useScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ export function useScript<T extends Record<symbol | string, any> = Record<symbol
id,
status: 'awaitingLoad',
remove() {
// cancel any pending triggers as we've started loading
script._triggerAbortController?.abort()
script._triggerPromises = [] // clear any pending promises
if (script.entry) {
script.entry.dispose()
syncStatus('removed')
Expand Down Expand Up @@ -150,22 +153,33 @@ export function useScript<T extends Record<symbol | string, any> = Record<symbol
script.load()
}
else if (trigger instanceof Promise) {
script._triggerAbortController = script._triggerAbortController || new AbortController()
// promise triggers only work client side
if (head.ssr) {
return
}
if (!script._triggerAbortController) {
script._triggerAbortController = new AbortController()
script._triggerAbortPromise = new Promise<void>((resolve) => {
script._triggerAbortController!.signal.addEventListener('abort', () => {
script._triggerAbortController = null
resolve()
})
})
}
script._triggerPromises = script._triggerPromises || []
const idx = script._triggerPromises.push(Promise.race([
trigger.then(v => typeof v === 'undefined' || v ? script.load : undefined),
new Promise<void>((resolve) => {
script._triggerAbortController!.signal.addEventListener('abort', () => resolve())
}),
]).then((res) => {
res?.()
// remove the promise from the list
script._triggerPromises?.splice(idx, 1)
}))
script._triggerAbortPromise,
])
// OK
.catch(() => {})
.then((res) => {
res?.()
})
.finally(() => {
// remove the promise from the list
script._triggerPromises?.splice(idx, 1)
}))
}
else if (typeof trigger === 'function') {
trigger(script.load)
Expand Down

0 comments on commit 7a026f4

Please sign in to comment.