使用 DI 将窗口对象注入到 Angular 的组件中

Ari*_*ris 1 ionic-framework ionic2 angular

我在我的应用程序中加载 socket.io,如下所示:

index.html
<script src="http://myapp.com/socket.io/socket.io.js"></script>
...
// Angular stuff
Run Code Online (Sandbox Code Playgroud)

我有一个Socket需要window.io工作的组件。

import { Injectable } from '@angular/core';
import { Events } from 'ionic-angular';

@Injectable()
export class Socket {

  public isConnected: boolean = false;

  constructor(public events: Events) {
    if (typeof window.io === "undefined") {
        throw new Error("Socket.io is undefined.");
    }

    this.io = window.io;
  }

  connect() {
    this.io.connect("...");
  }

  listen() {

  }

}
Run Code Online (Sandbox Code Playgroud)

从理论上讲,它可能有效(未测试),但将窗口范围内的内容注入类并不是一个好习惯。

有没有办法做到这一点:

import { SocketIODriver } from 'socket.io';
import { Socket } from 'App/Socket/Socket';

@Component({
   templateUrl: 'layout.html'
})
export class ConferenceApp {
   constructor(
     public io: io,
     public Socket: Socket
   ) {
      this.socket = new Socket(new SocketIODriver());
   }
}
Run Code Online (Sandbox Code Playgroud)

谢谢你。

附言。IIRC,socket.io 必须从服务器加载,这就是我从我的服务器加载它的原因。如果能放到我的JS文件夹里就更好了。

mfr*_*het 5

虽然这似乎仍然适用于 Angular 8,但要小心,这是一个旧的答案

Angular > 1 适用于注入器。每个注入器都限定于一个特定的模块,并提供您希望模块接收的数据。

例如,您可以定义形状的对象: { useValue: 'theValueToInject' }并使其在树的任何级别可用。

如果你想为你的模块提供这样一个对象,你将不得不依赖装饰器的providers属性@NgModule。然后你可以使用构造你自己的对象

{provide: 'NameToInvoke', useValue: alreadyInitializedValue}

由于window已经是实例化对象,您可以依靠这种方法将其提供给您的模块:

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
    { provide: 'Window', useValue: window }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Run Code Online (Sandbox Code Playgroud)

因此,您可以像这样使用它:

constructor(@Inject('Window') private window: any) {} // or window type, I don't know what it's exactly
Run Code Online (Sandbox Code Playgroud)