Skip to content

Commit c7a277d

Browse files
committed
fix: manage global timer
1 parent fbdfcf5 commit c7a277d

File tree

2 files changed

+51
-42
lines changed

2 files changed

+51
-42
lines changed

docs/server.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const execa = require('execa')
77
const log = console.log
88
const PORT = 8899
99

10-
function sendData (statusCode, type, body, res) {
10+
function sendData(statusCode, type, body, res) {
1111
res.writeHead(statusCode, {
1212
'Content-type': `${type}`,
1313
'Content-Encoding': 'gzip'
@@ -16,7 +16,7 @@ function sendData (statusCode, type, body, res) {
1616
res.end(response)
1717
}
1818

19-
(async function build () {
19+
;(async function build() {
2020
await execa('yarn', ['run', 'build:dev', '--watch'], { stdio: 'inherit' })
2121
})()
2222

@@ -25,7 +25,7 @@ const server = http.createServer((req, res) => {
2525

2626
// 以运行 node docs/server.js 的路径为基路径,而不是 server.js 所在路径
2727
const html = fs.readFileSync('docs/dev-page.html')
28-
const jsonp = fs.readFileSync('dist/better-jsonp.min.js')
28+
const jsonp = fs.readFileSync('dist/better-jsonp.js')
2929
const client = fs.readFileSync('docs/index.js')
3030

3131
switch (true) {
@@ -53,4 +53,6 @@ const server = http.createServer((req, res) => {
5353

5454
server.listen(PORT)
5555

56-
log(chalk.yellow(`Server listening at port http://localhost:${chalk.green(PORT)}`))
56+
log(
57+
chalk.yellow(`Server listening at port http://localhost:${chalk.green(PORT)}`)
58+
)

lib/core/Jsonp.ts

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { options } from '../utils/types'
2-
import { noop, euc } from '../utils/index'
2+
import { noop } from '../utils/index'
33

44
const PREFIX = 'callback'
55

@@ -10,9 +10,9 @@ export default class Jsonp {
1010
private _jsonpCallback: string // response handler
1111
private _reference: Element // reference element
1212
private _script: HTMLScriptElement | null // trigger element
13-
private _timer: number // timer ID
13+
private _timer: number
1414

15-
constructor ({
15+
constructor({
1616
url,
1717
timeout = 6000,
1818
jsonpCallback = `${PREFIX}${Date.now()}`,
@@ -23,32 +23,32 @@ export default class Jsonp {
2323
url,
2424
jsonpCallback
2525
})
26-
this.initState({
27-
timeout,
28-
jsonpCallback
29-
})
3026
this.encodeURL({
3127
url,
3228
callbackParams,
3329
urlParams
3430
})
31+
this.initState({
32+
timeout,
33+
jsonpCallback
34+
})
3535
this.insert(this._url)
3636
}
3737

38-
checkOptions ({
39-
url,
40-
jsonpCallback
41-
}: options) {
38+
checkOptions({ url, jsonpCallback }: options) {
4239
if (!url) throw new Error('Please check your request url.')
4340

4441
// Every jsonp request will reset global request function named value of
4542
// jsonpCallback, so this value MUST NOT be `jsonp`.
4643

4744
// This checking only works in CDN installing, not as a dependency using
48-
if (jsonpCallback === 'jsonp') throw new Error('Don\'t name jsonpCallback to `jsonp` for unexpected reset. Please use any non-jsonp value')
45+
if (jsonpCallback === 'jsonp')
46+
throw new Error(
47+
"Don't name jsonpCallback to `jsonp` for unexpected reset. Please use any non-jsonp value"
48+
)
4949
}
5050

51-
initState ({
51+
initState({
5252
timeout,
5353
jsonpCallback
5454
}: {
@@ -67,79 +67,86 @@ export default class Jsonp {
6767
this.createTimer(timeout)
6868
}
6969

70-
createScript () {
71-
this._reference = document.getElementsByTagName('script')[0]
72-
|| document.body.lastElementChild
70+
createScript() {
71+
this._reference =
72+
document.getElementsByTagName('script')[0] ||
73+
document.body.lastElementChild
7374
this._script = document.createElement('script')
7475
}
7576

7677
/**
7778
* 1. Request timer will be cleaned when response handler invoked.
7879
* 2. use arrow function to keep `this` keywords value (Jsonp instance).
7980
*/
80-
createHandler () {
81-
return new Promise((resolve, reject) => {
81+
createHandler() {
82+
return new Promise<object>((resolve, reject) => {
8283
// handle 404/500 in response
8384
this._script.onerror = () => {
8485
this.cleanScript()
85-
reject(new Error(`Countdown has been clear! JSONP request unsuccessfully due to 404/500`))
86+
// clear timer
87+
if (this._timer) {
88+
window.clearTimeout(this._timer)
89+
this._timer = null
90+
}
91+
reject(
92+
new Error(
93+
`[SCRIPT ONERROR]: JSONP request unsuccessfully due to 404/500`
94+
)
95+
)
8696
}
87-
88-
(<any>window)[this._jsonpCallback] = (data: object) => {
97+
;(window as any)[this._jsonpCallback] = (data: object) => {
8998
this.cleanScript()
9099
resolve(data)
91100
}
92101
})
93102
}
94103

95104
// create a request timer for limiting request period
96-
createTimer (timeout: options['timeout']) {
105+
createTimer(timeout: options['timeout']) {
97106
// It can be disable when param timeout equal falsy value (0, null etc.)
98107
if (timeout) {
99-
this._timer = window.setTimeout(() => {
100-
(<any>window)[this._jsonpCallback] = noop
101-
this._timer = null
108+
const id = window.setTimeout(() => {
109+
;(window as any)[this._jsonpCallback] = noop
102110
this.cleanScript()
103-
throw new Error('JSONP request unsuccessfully (eg.timeout or wrong url).')
111+
this._timer = null
112+
throw new Error(
113+
'[TIMEOUT]: JSONP request unsuccessfully (eg.timeout or wrong url).'
114+
)
104115
}, timeout)
116+
this._timer = id
105117
}
106118
}
107119

108-
encodeURL ({
109-
url,
110-
callbackParams,
111-
urlParams
112-
}: options) {
120+
encodeURL({ url, callbackParams, urlParams }: options) {
113121
// name of query parameter to specify the callback name
114122
// eg. ?callback=...
115-
const id = euc(this._jsonpCallback)
123+
const id = encodeURIComponent(this._jsonpCallback)
116124
url += `${url.indexOf('?') < 0 ? '?' : '&'}${callbackParams}=${id}`
117125

118126
// add other parameters to url ending excluding callback name parameter
119127
const keys = Object.keys(urlParams)
120128
keys.forEach(key => {
121129
const value = urlParams[key] !== undefined ? urlParams[key] : ''
122-
url += `&${key}=${euc(value)}`
130+
url += `&${key}=${encodeURIComponent(value)}`
123131
})
124132

125133
// converted request url
126134
this._url = url
127135
}
128136

129137
// activate JSONP
130-
insert (url: string) {
138+
insert(url: string) {
131139
this._script.src = url
132140
this._reference.parentNode.insertBefore(this._script, this._reference)
133141
}
134142

135-
cleanScript () {
136-
if (this._script.parentNode) {
143+
cleanScript() {
144+
if (this._script && this._script.parentNode) {
137145
this._script.parentNode.removeChild(this._script)
138146
this._script = null
139147
}
140148

141149
// reset response handler
142-
(<any>window)[this._jsonpCallback] = noop
143-
if (this._timer) window.clearTimeout(this._timer)
150+
;(window as any)[this._jsonpCallback] = noop
144151
}
145152
}

0 commit comments

Comments
 (0)