Как перейти к компоненту Angular только после загрузки всех скриптов в Resolver? - PullRequest
0 голосов
/ 26 октября 2018

У меня есть задача загрузить 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 для контроля загрузки скриптов, до того, как распознаватель был сервисом с обещаниями, но он также выдавал ту же ошибку.

...