我有一个angular-cli生成的项目,希望与deployd后端一起使用。deployd提供了一个脚本,用于访问可以从http://<deployd-host>/dpd.js加载的api。这将创建一个全局dpd对象,该对象可以从javascript全局上下文(例如,从chrome开发工具控制台)访问api。
我想把这个封装在angular2服务中,这样我就可以插入一个模拟的服务来进行测试等。任务是从url加载脚本,然后获得对globaldpd对象的访问权。我已经看过了this的文章,但还没能得到公认的答案。如果我手动将脚本添加到document对象,则无法访问window上的dpd对象。
此外,脚本从中加载的url将根据环境而有所不同,例如,对于本地开发人员,http://localhost:3000/dpd.js用于登台,对于生产环境,http://dev.example.com/dpd.js用于生产。所以理想情况下,我也可以在服务中配置它。
找下面这样的工作。

@Injectable()
export class DpdService {
  constructor() {
    if (getEnvironmentSomeHow() == 'development') {
      loadScriptFrom("http://localhost:3000/dpd.js");
    } else {
      loadScriptFrom("http://dev.example.com/dpd.js");
    }
    dpd = window.dpd;
  }

  public session(): Observable<Session> {
    return Observable.fromPromise(dpd.sessions.get());
  }
}

最佳答案

应用程序环境完全取决于开发人员的选择。这些文件可以是依赖于节点环境变量的有条件包含的TS文件。它可以是一个单独的文件,根据客户端全局变量定义角度提供者(例如,可能随webpackDefinePluginEnvironmentPlugin提供,请参见angular2-webpack-starter)。它最简单的形式就是客户端全局变量,所有的决定都是在适当的地方做出的,甚至可以用服务器端模板在html中设置:

<script>
   window.ENV = <% SERVER_SIDE_ENV_VARIABLE %>
</script>

由于脚本应在应用程序初始化时加载,因此必须在ENV多提供程序中加载:
...
import {APP_INITIALIZER} from '@angular/core'
import {DOCUMENT} from '@angular/platform-browser'

@Injectable()
export class DpdService {
  dpd: any;

  constructor(@Inject(DOCUMENT) document: Document) {}

  load() {
    const srcBase = window.ENV === 'dev'
      ? 'http://localhost:3000/'
      : 'http://dev.example.com/';

    const script = this.document.createElement('script');
    this.document.body.appendChild(script);

    return new Promise((resolve, reject) => {
      script.onload = resolve;
      script.onerror = reject;
      script.async = true;
      script.src = srcBase + 'dpd.js';
    }).then(() => {
      this.dpd = window.dpd;
    });
  }

  session(): Observable<Session> {
    return Observable.fromPromise(this.dpd.sessions.get());
  }
}

export function dpdAppInitializerFactory(dpdService: DpdService) {
  return () => dpdService.load();
}

...
providers: [
  DpdService,
  {
    provide: APP_INITIALIZER,
    useFactory: dpdAppInitializerFactory,
    deps: [DpdService],
    multi: true
  }
],


在应用程序初始化时,实现了APP_INITIALIZER方法的承诺,并设置了load属性。

07-24 20:26