Skip to content

Commit 104cbf2

Browse files
committed
fix duplicate requests
1 parent 25e804d commit 104cbf2

3 files changed

Lines changed: 63 additions & 43 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-async-script-loader",
3-
"version": "0.1.1",
3+
"version": "0.2.0",
44
"description": "A decorator for script lazy loading on react component",
55
"main": "lib/index.js",
66
"scripts": {

src/index.js

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,77 @@ import hoistStatics from 'hoist-non-react-statics'
33
import { isDefined, newScript, series, noop } from './utils'
44

55
const loadedScript = []
6+
const pendingScripts = {}
67
let failedScript = []
78

8-
const scriptLoader = (...scripts) => (WrappedComponent) => {
9+
export function startLoadingScripts(scripts, onComplete = noop) {
10+
// sequence load
11+
const loadNewScript = (src) => {
12+
if (loadedScript.indexOf(src) < 0) {
13+
return taskComplete => {
14+
const callbacks = pendingScripts[src] || []
15+
callbacks.push(taskComplete)
16+
pendingScripts[src] = callbacks
17+
if (callbacks.length === 1) {
18+
return newScript(src)(err => {
19+
pendingScripts[src].forEach(cb => cb(err, src))
20+
delete pendingScripts[src]
21+
})
22+
}
23+
}
24+
}
25+
}
26+
const tasks = scripts.map(src => {
27+
if (Array.isArray(src)) {
28+
return src.map(loadNewScript)
29+
}
30+
else return loadNewScript(src)
31+
})
932

10-
const addCache = (entry) => {
11-
if (loadedScript.indexOf(entry) < 0) {
12-
loadedScript.push(entry)
33+
series(...tasks)((err, src) => {
34+
if (err) {
35+
failedScript.push(src)
36+
}
37+
else {
38+
if (Array.isArray(src)) {
39+
src.forEach(addCache)
40+
}
41+
else addCache(src)
1342
}
43+
})(err => {
44+
removeFailedScript()
45+
onComplete(err)
46+
})
47+
}
48+
49+
const addCache = (entry) => {
50+
if (loadedScript.indexOf(entry) < 0) {
51+
loadedScript.push(entry)
1452
}
53+
}
1554

16-
const removeFailedScript = () => {
17-
if (failedScript.length > 0) {
18-
failedScript.forEach((script) => {
19-
const node = document.querySelector(`script[src='${script}']`)
20-
if (node != null) {
21-
node.parentNode.removeChild(node)
22-
}
23-
})
55+
const removeFailedScript = () => {
56+
if (failedScript.length > 0) {
57+
failedScript.forEach((script) => {
58+
const node = document.querySelector(`script[src='${script}']`)
59+
if (node != null) {
60+
node.parentNode.removeChild(node)
61+
}
62+
})
2463

25-
failedScript = []
26-
}
64+
failedScript = []
2765
}
66+
}
2867

68+
const scriptLoader = (...scripts) => (WrappedComponent) => {
2969
class ScriptLoader extends Component {
3070
static propTypes = {
3171
onScriptLoaded: T.func
32-
};
72+
}
3373

3474
static defaultProps = {
3575
onScriptLoaded: noop
36-
};
76+
}
3777

3878
constructor (props, context) {
3979
super(props, context)
@@ -45,30 +85,7 @@ const scriptLoader = (...scripts) => (WrappedComponent) => {
4585
}
4686

4787
componentDidMount () {
48-
// sequence load
49-
const loadNewScript = (src) => {
50-
if (loadedScript.indexOf(src) < 0) return newScript(src)
51-
}
52-
const tasks = scripts.map(src => {
53-
if (Array.isArray(src)) {
54-
return src.map(loadNewScript)
55-
}
56-
else return loadNewScript(src)
57-
})
58-
59-
series(...tasks)((err, src) => {
60-
if (err) {
61-
failedScript.push(src)
62-
}
63-
else {
64-
if (Array.isArray(src)) {
65-
src.forEach(addCache)
66-
}
67-
else addCache(src)
68-
}
69-
})(err => {
70-
removeFailedScript()
71-
88+
startLoadingScripts(scripts, err => {
7289
this.setState({
7390
isScriptLoaded: true,
7491
isScriptLoadSucceed: !err

test/index.spec.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ function renderTestComponent (deps, onScriptLoaded) {
1818
function checkScriptLoaded (getComponent, done) {
1919
return _ => {
2020
const com = getComponent()
21-
console.log(com)
2221

2322
expect(com.props.isScriptLoaded).to.be.true
2423
expect(com.props.isScriptLoadSucceed).to.be.true
@@ -33,6 +32,8 @@ describe('Test this module', _ => {
3332
const deps = [ '//cdn.bootcss.com/jquery/2.2.1/jquery.min.js' ]
3433
const com = renderTestComponent(deps, onScriptLoaded)
3534

35+
this.timeout(5000)
36+
3637
// check script tags
3738
deps.forEach(testScript => {
3839
const tag = document.querySelector(`script[src='${testScript}']`)
@@ -54,11 +55,13 @@ describe('Test this module', _ => {
5455

5556
it('[react-async-script-loader] No redundant script tag will be appended',
5657
function (done) {
57-
const deps = [ '//cdn.bootcss.com/jquery/2.2.1/jquery.min.js' ]
58+
const deps = [ '//cdn.bootcss.com/jquery/2.1.1/jquery.min.js' ]
5859
const com0 = renderTestComponent(deps, checkScriptLoaded(_ => com0, checkAllDone))
5960
const com1 = renderTestComponent(deps, checkScriptLoaded(_ => com1, checkAllDone))
6061
let count = 0
6162

63+
this.timeout(5000)
64+
6265
// check script tags
6366
deps.forEach(testScript => {
6467
const tags = document.querySelectorAll(`script[src='${testScript}']`)

0 commit comments

Comments
 (0)