diff --git a/src/create-script-loader.ts b/src/create-script-loader.ts index 6b7adca..4e8ec22 100644 --- a/src/create-script-loader.ts +++ b/src/create-script-loader.ts @@ -1,5 +1,5 @@ import ScriptLoader from './script-loader'; export default function createScriptLoader(): ScriptLoader { - return new ScriptLoader(document); + return new ScriptLoader(); } diff --git a/src/get-script-loader.spec.ts b/src/get-script-loader.spec.ts new file mode 100644 index 0000000..7c829f5 --- /dev/null +++ b/src/get-script-loader.spec.ts @@ -0,0 +1,12 @@ +import getScriptLoader from './get-script-loader'; +import ScriptLoader from './script-loader'; + +describe('getScriptLoader()', () => { + it('returns same `ScriptLoader` instance', () => { + const loader = getScriptLoader(); + const loader2 = getScriptLoader(); + + expect(loader).toBe(loader2); + expect(loader).toBeInstanceOf(ScriptLoader); + }); +}); diff --git a/src/get-script-loader.ts b/src/get-script-loader.ts new file mode 100644 index 0000000..baf2c44 --- /dev/null +++ b/src/get-script-loader.ts @@ -0,0 +1,12 @@ +import ScriptLoader from './script-loader'; +import createScriptLoader from './create-script-loader'; + +let instance: ScriptLoader; + +export default function getScriptLoader(): ScriptLoader { + if (!instance) { + instance = createScriptLoader(); + } + + return instance; +} diff --git a/src/index.ts b/src/index.ts index 353618f..b9fb0a5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,3 @@ export { default as ScriptLoader } from './script-loader'; export { default as createScriptLoader } from './create-script-loader'; +export { default as getScriptLoader } from './get-script-loader'; diff --git a/src/script-loader.spec.ts b/src/script-loader.spec.ts index 7574e54..83bbd90 100644 --- a/src/script-loader.spec.ts +++ b/src/script-loader.spec.ts @@ -12,7 +12,7 @@ describe('ScriptLoader', () => { element.onreadystatechange(new Event('readystatechange')) ); - loader = new ScriptLoader(document); + loader = new ScriptLoader(); }); afterEach(() => { @@ -43,4 +43,11 @@ describe('ScriptLoader', () => { expect(output).toBeInstanceOf(Event); } }); + + it('does not load same script twice', async () => { + await loader.loadScript('https://code.jquery.com/jquery-3.2.1.min.js'); + await loader.loadScript('https://code.jquery.com/jquery-3.2.1.min.js'); + + expect(document.body.appendChild).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/script-loader.ts b/src/script-loader.ts index c84fbce..3964743 100644 --- a/src/script-loader.ts +++ b/src/script-loader.ts @@ -1,20 +1,22 @@ export default class ScriptLoader { - constructor( - private _document: Document - ) {} + private _scripts: { [key: string]: Promise } = {}; loadScript(src: string): Promise { - return new Promise((resolve, reject) => { - const script = this._document.createElement('script') as LegacyHTMLScriptElement; + if (!this._scripts[src]) { + this._scripts[src] = new Promise((resolve, reject) => { + const script = document.createElement('script') as LegacyHTMLScriptElement; - script.onload = (event) => resolve(event); - script.onreadystatechange = (event) => resolve(event); - script.onerror = (event) => reject(event); - script.async = true; - script.src = src; + script.onload = (event) => resolve(event); + script.onreadystatechange = (event) => resolve(event); + script.onerror = (event) => reject(event); + script.async = true; + script.src = src; - this._document.body.appendChild(script); - }); + document.body.appendChild(script); + }); + } + + return this._scripts[src]; } }