我有一個典型的用例,我必須使用不同的端點websocket URL來連接不同的後端服務。Angular 2:如何在創建之前傳遞服務配置?
我已經寫了通用的服務在角2見下圖:
import {Injectable} from "@angular/core";
import {Subject} from "rxjs/subject";
import {Observable} from "rxjs/observable";
import {WebSocketSubject, WebSocketSubjectConfig} from "rxjs/observable/dom/WebSocketSubject";
import {Observer} from "rxjs/observer";
@Injectable()
export class WebSocketService<T> extends Subject<T> {
private reconnectionObservable: Observable<number>;
private wsSubjectConfig: WebSocketSubjectConfig;
private socket: WebSocketSubject<any>;
private connectionObserver: Observer<boolean>;
public connectionStatus: Observable<boolean>;
constructor(private config: WebServiceConfig) {
super();
// connection status
this.connectionStatus = new Observable((observer) => {
this.connectionObserver = observer;
}).share().distinctUntilChanged();
// config for WebSocketSubject
// except the url, here is closeObserver and openObserver to update connection status
this.wsSubjectConfig = {
url: config.URL,
closeObserver: {
next: (e:CloseEvent) => {
this.socket = null;
this.connectionObserver.next(false);
}
},
openObserver: {
next: (e:Event) => {
this.connectionObserver.next(true);
}
}
};
this.connect();
// we follow the connection status and run the reconnect while losing the connection
this.connectionStatus.subscribe((isConnected) => {
if (!this.reconnectionObservable && typeof(isConnected) == "boolean" && !isConnected) {
this.reconnect();
}
});
}
connect():void {
this.socket = new WebSocketSubject(this.wsSubjectConfig);
this.socket.subscribe(
(m) => {
this.next(m); // when receiving a message, we just send it to our Subject
},
(error:Event) => {
if (!this.socket) {
// in case of an error with a loss of connection, we restore it
this.reconnect();
}
});
}
reconnect():void {
this.reconnectionObservable = Observable.interval(this.config.getRetryInterval())
.takeWhile((v, index) => {
return index < this.config.attempts && !this.socket
});
this.reconnectionObservable.subscribe(
() => {
this.connect();
},
null,
() => {
// if the reconnection attempts are failed, then we call complete of our Subject and status
this.reconnectionObservable = null;
if (!this.socket) {
this.complete();
this.connectionObserver.complete();
}
});
}
send(data:any):void {
this.socket.next(this.config.serializer(data));
}
}
export enum TimeUnits {
SECONDS = 1000,
MINUTES = SECONDS * 60,
HOURS = MINUTES * 60,
DAYS = HOURS * 24
}
export class WebServiceConfig {
URL: string = 'ws://localhost:4242/ws';
attempts: number = 10; /// number of connection attempts
retryUnit: TimeUnits = TimeUnits.SECONDS; /// pause between connections
retryInterval: number = 5;
serializer: (data: any) => any = function (data: any) {
return JSON.stringify(data);
};
deserializer: (e: MessageEvent) => any = function (e: MessageEvent) {
return e;
};
getRetryInterval(): number {
return this.retryUnit * this.retryInterval;
};
}
現在的問題是如何創建具有不同配置的新實例?
我認爲的一種方法是擴展到子類並通過配置。有更好的方法來創建擴展類嗎?
配置是動態的!我的意思是它將寫入服務器端的頁面(我們使用後端的句柄來渲染模板)。
謝謝你,我已經實現了這個解決方案,這一方式允許隔離(限制範圍)到模塊或組件。 – user3130446