/
load-script.ts
101 lines (89 loc) 路 2.47 KB
/
load-script.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { isDev } from '~/lib/env'
const isLoadScriptMap: Record<string, 'loading' | 'loaded'> = {}
const loadingQueueMap: Record<string, [Function, Function][]> = {}
export function loadScript(url: string) {
return new Promise((resolve, reject) => {
const status = isLoadScriptMap[url]
if (status === 'loaded') {
return resolve(null)
} else if (status === 'loading') {
loadingQueueMap[url] = !loadingQueueMap[url]
? [[resolve, reject]]
: [...loadingQueueMap[url], [resolve, reject]]
return
}
const script = document.createElement('script')
script.src = url
script.crossOrigin = 'anonymous'
isLoadScriptMap[url] = 'loading'
script.onload = function () {
isLoadScriptMap[url] = 'loaded'
resolve(null)
if (loadingQueueMap[url]) {
loadingQueueMap[url].forEach(([resolve]) => {
resolve(null)
})
delete loadingQueueMap[url]
}
}
if (isDev) {
console.log('load script: ', url)
}
script.onerror = function (e) {
// this.onload = null here is necessary
// because even IE9 works not like others
this.onerror = this.onload = null
delete isLoadScriptMap[url]
loadingQueueMap[url].forEach(([, reject]) => {
reject(e)
})
delete loadingQueueMap[url]
reject(e)
}
document.head.appendChild(script)
})
}
const cssMap = new Map<string, HTMLLinkElement>()
export function loadStyleSheet(href: string) {
if (cssMap.has(href)) {
const $link = cssMap.get(href)!
return {
$link,
remove: () => {
$link.parentNode && $link.parentNode.removeChild($link)
cssMap.delete(href)
},
}
}
const $link = document.createElement('link')
$link.href = href
$link.rel = 'stylesheet'
$link.type = 'text/css'
$link.crossOrigin = 'anonymous'
cssMap.set(href, $link)
$link.onerror = () => {
$link.onerror = null
cssMap.delete(href)
}
document.head.appendChild($link)
return {
remove: () => {
$link.parentNode && $link.parentNode.removeChild($link)
cssMap.delete(href)
},
$link,
}
}
export function appendStyle(style: string) {
let $style: HTMLStyleElement | null = document.createElement('style')
$style.innerHTML = style
document.head.appendChild($style)
return {
remove: () => {
if (!$style) return
$style.parentNode && $style.parentNode.removeChild($style)
$style.remove()
$style = null
},
}
}