У меня есть задача загрузить 3 скрипта из корзины Amazon S3 до загрузки компонента, потому что он использует логику, которая есть в этих скриптах. Итак, у меня есть resolver , который добавляет теги сценария к HEAD :
private scripts: ScriptModel[] = [];
private envScripts: ScriptModel[];
constructor(
private appState: AppState
) {
// empty
}
public resolve() {
console.log('Resolver');
const environment = this.appState.restore('environment');
forkJoin(this.load(environment))
.subscribe(
() => { /* empty */ console.log('Scripts loaded'); },
(error: any) => { console.log(`Error to load scripts for preview: `, error); }
);
}
public load(env: string) {
this.envScripts = ScriptStore[env].map((_script: ScriptModel) => ({ name: _script.name, src: _script.src, loaded: _script.loaded }));
const scripts: ScriptModel[] = this.envScripts.map((_script: ScriptModel) => this.loadScript(_script));
return scripts;
}
public loadScript(script: ScriptModel) {
return Observable.create((observer: Observer<ScriptModel>) => {
const existingScript = this.scripts.find((_script: ScriptModel) => _script.name === script.name);
if (!!existingScript && existingScript.loaded) {
observer.next(existingScript);
observer.complete();
} else {
this.scripts = [...this.scripts, script];
const scriptElement = document.createElement('script');
scriptElement.type = 'text/javascript';
scriptElement.src = script.src;
scriptElement.onload = () => {
script.loaded = true;
observer.next(script);
observer.complete();
};
scriptElement.onerror = () => {
observer.error(`Couldn't load script ${script.name}, ${script.src}`);
};
document.querySelector('head').appendChild(scriptElement);
}
});
}
ScriptStore содержит скрипты в соответствии с именем среды, ScriptModel - это интерфейс для описания того, как он должен выглядеть:
export interface ScriptModel {
name: string;
src: string;
loaded: boolean;
}
И у меня проблема в том, что иногда код в компоненте выдает ошибку, что функция из этих дополнительных сценариев не определена. Как я понял, это потому, что код в компоненте выполняется до загрузки этих скриптов. В компоненте некоторый код начинает работать в конструкторе , а основная функция вызывается в ngOnInit . Но компонент не должен загружаться до завершения распознавателя. Нужно ли мне возвращать Observable / Promise в распознаватель? Как я должен сделать это правильно? Resolver должен быть завершен, только если загружены все сценарии. Я использую Observables для контроля загрузки скриптов, до того, как распознаватель был сервисом с обещаниями, но он также выдавал ту же ошибку.