Skip to content

Commit 871ae47

Browse files
committed
fix(core): CHECKOUT-3012 Avoid loading the same script twice
1 parent 67a1b46 commit 871ae47

6 files changed

Lines changed: 48 additions & 14 deletions

File tree

src/create-script-loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import ScriptLoader from './script-loader';
22

33
export default function createScriptLoader(): ScriptLoader {
4-
return new ScriptLoader(document);
4+
return new ScriptLoader();
55
}

src/get-script-loader.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import getScriptLoader from './get-script-loader';
2+
import ScriptLoader from './script-loader';
3+
4+
describe('getScriptLoader()', () => {
5+
it('returns same `ScriptLoader` instance', () => {
6+
const loader = getScriptLoader();
7+
const loader2 = getScriptLoader();
8+
9+
expect(loader).toBe(loader2);
10+
expect(loader).toBeInstanceOf(ScriptLoader);
11+
});
12+
});

src/get-script-loader.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import ScriptLoader from './script-loader';
2+
import createScriptLoader from './create-script-loader';
3+
4+
let instance: ScriptLoader;
5+
6+
export default function getScriptLoader(): ScriptLoader {
7+
if (!instance) {
8+
instance = createScriptLoader();
9+
}
10+
11+
return instance;
12+
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { default as ScriptLoader } from './script-loader';
22
export { default as createScriptLoader } from './create-script-loader';
3+
export { default as getScriptLoader } from './get-script-loader';

src/script-loader.spec.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('ScriptLoader', () => {
1212
element.onreadystatechange(new Event('readystatechange'))
1313
);
1414

15-
loader = new ScriptLoader(document);
15+
loader = new ScriptLoader();
1616
});
1717

1818
afterEach(() => {
@@ -43,4 +43,11 @@ describe('ScriptLoader', () => {
4343
expect(output).toBeInstanceOf(Event);
4444
}
4545
});
46+
47+
it('does not load same script twice', async () => {
48+
await loader.loadScript('https://code.jquery.com/jquery-3.2.1.min.js');
49+
await loader.loadScript('https://code.jquery.com/jquery-3.2.1.min.js');
50+
51+
expect(document.body.appendChild).toHaveBeenCalledTimes(1);
52+
});
4653
});

src/script-loader.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
export default class ScriptLoader {
2-
constructor(
3-
private _document: Document
4-
) {}
2+
private _scripts: { [key: string]: Promise<Event> } = {};
53

64
loadScript(src: string): Promise<Event> {
7-
return new Promise((resolve, reject) => {
8-
const script = this._document.createElement('script') as LegacyHTMLScriptElement;
5+
if (!this._scripts[src]) {
6+
this._scripts[src] = new Promise((resolve, reject) => {
7+
const script = document.createElement('script') as LegacyHTMLScriptElement;
98

10-
script.onload = (event) => resolve(event);
11-
script.onreadystatechange = (event) => resolve(event);
12-
script.onerror = (event) => reject(event);
13-
script.async = true;
14-
script.src = src;
9+
script.onload = (event) => resolve(event);
10+
script.onreadystatechange = (event) => resolve(event);
11+
script.onerror = (event) => reject(event);
12+
script.async = true;
13+
script.src = src;
1514

16-
this._document.body.appendChild(script);
17-
});
15+
document.body.appendChild(script);
16+
});
17+
}
18+
19+
return this._scripts[src];
1820
}
1921
}
2022

0 commit comments

Comments
 (0)