結果不是rxjs的問題,而是如果 angent.component
的 constructor 沒有寫成這樣,或者沒在任何一個component的constuctor寫下這樣的宣告就會發生標題的問題
angent.component
import {agantCtr} from 'src/myservice/agentCtr.service'
import {socketService} from 'src/myservice/socket.service'
constructor(private agantCtr: agantCtr,
private socketService: socketService
) { }
若這邊把private socketService: socketService
拿掉,則socketService
就無法取用angent.component
在 agentCtr.service
中所更動的值了。
這是angular的時麼保護機制嗎?有點玄妙,官網上說明明說service是singleton
啊...
當 websocket.service
中的某個subscribe, 呼叫了agentCtr.service
中的某個function時,agentCtr.service
的 this
無法訪問 部分的
property。
websocket.service // 提供前端網頁reactive update的服務(後端API觸發後 會send message到前端來解析要觸發哪些update)
agentCtr.service // 負責 angent.component
的資料更新
angent.component // component "Oninit時,會初始化agentCtr.service
agentCtr.service
中有一個subject,而angent.component
利用此subject來設定此agentCtr.service
的一些參數,例如 server的ip/port 或 userId之類的 URL參數,當
@Injectable({
providedIn: 'root'
})
export class socketService {
// SubjectList
/**
* Websocket
* 當socket接收到訊息時,解析並調用指定函數
*
*/
websocket = webSocket<any>(environment.socket);
constructor(public agentCtr: agantCtr){
console.log('socket service init')
// socket subscribe
this.websocket.subscribe(
onMsg => {
let res = onMsg as socketReponse
console.log({incommingSocketRes: res})
if(res.action === 'message') {
console.log({socketMessage: res.body})
}
else if (res.action === 'update') {
// 這個地方 userId 是正確的,curWs是空字串。
console.log({peekAgentCurWs: this.agentCtr.curWs})
console.log({peekAgentCuruserid: this.agentCtr.userId})
let body = res.body as forceUpdate
if(body.target === 'batchComponent') {
// 這邊呼叫時,getBatchConf中this.userId可以讀取得到
// getBatchConf中this.curWs是空白的值,但應該要有才對
this.agentCtr.getBatchConf()
}
}
},
err => {
},
() => {
console.log()
}
)
}
}
@Injectable({
providedIn: 'root'
})
export class agantCtr {
userId: string = '';
curWs: string = '';
// angent.component 會利用此 Subject 來觸發更新
currentWs = new Subject<string>();
constructor(private cookieService: CookieService){
// set
userId = this.cookieService.get(cookieList.userID);
// 當angent.component OnInit時會pass值到currentWs這個Subject
this.currentWs.subscribe( wsname => {
console.log('switch workspace:'+ wsname)
// 當 workspace 切換時,載入相依資訊與相依設定
this.curWs = wsname
this.getBatchConf();
})
} // end constructor()
getBatchConf = () => {
// 當我從socket.service呼叫時,this.curWs遺失了
console.log('in get batchconfig of :' + this.curWs)
console.log('user: ' + this.userId)
let url = `http://${environment.apiserver}/users/${this.userId}/management/api/getBatchConfig/${this.curWs}`;
this.http.get(url, {
headers: {
},
withCredentials:true
}).subscribe(data => {
// do sth
})
}
switchWs(WsName: string) {
this.currentWs.next(WsName)
}
}
@Component({
selector: 'app-agent',
templateUrl: './agent.component.html',
styleUrls: ['./agent.component.css']
})
export class AgentComponent implements OnInit, OnDestroy {
constructor(private http: HttpClient,
private route: ActivatedRoute,
private router: Router,
private cookieService: CookieService,
public agentCtr: agantCtr, // angentCtr.service
private socketService: socketService) { }
ngOnInit(): void {
console.log('agent component init Start!')
this.userId = this.cookieService.get(cookieList.userID);
this.wsName = this.route.snapshot.parent.paramMap.get('wsName');
// 改變agent所代理的Ws(使set, get Api 針對目前正瀏覽的Ws做操作)
this.agentCtr.switchWs(this.wsName);