@segment/analytics-next
Version:
Analytics Next (aka Analytics 2.0) is the latest version of Segment’s JavaScript SDK - enabling you to send your data to any tool without having to learn, test, or use a new API every time.
77 lines (63 loc) • 1.92 kB
text/typescript
function findScript(src: string): HTMLScriptElement | undefined {
const scripts = Array.prototype.slice.call(
window.document.querySelectorAll('script')
)
return scripts.find((s) => s.src === src)
}
/**
* Load a script from a URL and append it to the document.
*/
export function loadScript(
src: string,
attributes?: Record<string, string>
): Promise<HTMLScriptElement> {
const found = findScript(src)
if (found !== undefined) {
const status = found?.getAttribute('status')
if (status === 'loaded') {
return Promise.resolve(found)
}
if (status === 'loading') {
return new Promise((resolve, reject) => {
found.addEventListener('load', () => resolve(found))
found.addEventListener('error', (err) => reject(err))
})
}
}
return new Promise((resolve, reject) => {
const script = window.document.createElement('script')
script.type = 'text/javascript'
script.src = src
script.async = true
script.setAttribute('status', 'loading')
for (const [k, v] of Object.entries(attributes ?? {})) {
script.setAttribute(k, v)
}
script.onload = (): void => {
script.onerror = script.onload = null
script.setAttribute('status', 'loaded')
resolve(script)
}
script.onerror = (): void => {
script.onerror = script.onload = null
script.setAttribute('status', 'error')
reject(new Error(`Failed to load ${src}`))
}
const firstExistingScript = window.document.querySelector('script')
if (!firstExistingScript) {
window.document.head.appendChild(script)
} else {
firstExistingScript.parentElement?.insertBefore(
script,
firstExistingScript
)
}
})
}
export function unloadScript(src: string): Promise<void> {
const found = findScript(src)
if (found !== undefined) {
found.remove()
}
return Promise.resolve()
}