import { Injectable , Inject } from '@angular/core' ; import { Observable } from 'rxjs' ; import { take , shareReplay } from 'rxjs/operators' ; import { DOCUMENT } from '@angular/common' ; @ Injectable ( { providedIn : 'root' } ) export class ScriptService { constructor ( @ Inject ( DOCUMENT ) private _document ) { } private scriptsLoaders : { [ url ] : Observable < Event > ; } = { } ; private _loadScript ( url , attributes ? , targetEl = 'head' ) { return new Observable < Event > ( ( observer ) => { const script = this . _document . createElement ( 'script' ) ; if ( attributes ) { for ( const key in attributes ) { if ( attributes . hasOwnProperty ( key ) ) { script . setAttribute ( key , attributes [ key ] ) ; } } } script . onload = ( event ) => { observer . next ( event ) ; observer . complete ( ) ; } ; script . onerror = err => { observer . error ( err ) ; } ; script . src = url ; const targetElement = typeof targetEl === 'string' ? this . _document . querySelector ( targetEl ) : targetEl ; targetElement . appendChild ( script ) ; } ) ; } param url param attributes param targetEl loadScript ( url , attributes ? , targetEl = 'head' ) { return this . scriptsLoaders [ url ] = this . scriptsLoaders [ url ] || this . _loadScript ( url , attributes , targetEl ) . pipe ( take ( 1 ) , shareReplay ( 1 ) ) ; } param url param attributes param targetEl runScript ( url , attributes ? , targetEl = 'head' ) { return this . _loadScript ( url , attributes , targetEl ) ; } }