im创建一个小型应用程序,每当将请求发送到服务器时,我都希望有一个activityIndicator。
因此,在我的UI服务中,我有一个Subject,并且我在ActivityIndicatorComponent中正在监听它。结果:它开始“忙”,但是即使指标属性“忙”中的变量为false也不会停止。
那么标识符一次初始化后就以某种方式“不刷新”了吗?
我的UIService
@Injectable({ providedIn: 'root'})
export class UiService {
private _drawerState= new BehaviorSubject<void>(null);
isLoading = new Subject<boolean>();
get drawerState() {
return this._drawerState.asObservable();
}
toggleDrawer() {
this._drawerState.next(null);
}
setIsLoading(value: boolean) {
this.isLoading.next(value);
}
}
我的Socket服务在Ui服务中调用方法:
export class SocketioService {
socket;
currentRoom: ChatRoom;
message_receiver = new Subject<Message>();
room_receiver = new Subject<ChatRoom>();
constructor(private router: RouterExtensions, private ui: UiService) {
this.socket = SocketIO.connect("http://localhost:3000");
console.log("SOCKET: " + this.socket);
this.socket.on("chat room", (room) => this.onReceivingChatRoom(room));
}
onRequestRoomlist(data) {
this.ui.setIsLoading(true);
this.socket.emit("request rooms", data);
}
onReceivingChatRoom(room) {
this.ui.setIsLoading(false);
console.log("Received Chat Room");
this.room_receiver.next(new ChatRoom(room.name, room.description, room.image, room.protection));
}
}
最后我在我的ActivityIndicatorComponent中听主题:
export class ActivityIndicatorComponent implements OnInit {
isLoading: boolean;
constructor(private ui: UiService) { }
ngOnInit() {
this.ui.isLoading.subscribe(
(value: boolean) => {
this.isLoading = value;
}
)
}
}
这是ActivityIndicatorComponent的xml
<ActivityIndicator #indicator row="1" col="1" width="50" height="50" busy="{{isLoading}}" color="#6495ed"></ActivityIndicator>
答案 0 :(得分:1)
套接字可能在Angular区域之外运行,因此,更改变量后,它将向您的主题发送更新,并且由于它在区域之外,因此不会触发更改检测。
这可以通过两种方式解决:
detectChanges()
ngZone.run(() => {/* code */});
的角区域内跑步您还可以使用此可观察的运算符来确保代码在区域内运行。
import { NgZone } from '@angular/core';
import { Observable } from 'rxjs/Observable';
export function enterZone(zone: NgZone) {
return <T>(source: Observable<T>) =>
new Observable<T>(observer =>
source.subscribe({
next: (x) => zone.run(() => observer.next(x)),
error: (err) => observer.error(err),
complete: () => observer.complete()
})
);
}
因此您可以使用:this.ui.isLoading.pipe(enterZone(ngZone)).subscribe()
。甚至更好,您可以在服务中定义:
isLoading$ = this.isLoading.pipe(enterZone(ngZone))
因此,您可以确定正在订阅isLoading$
的任何内容实际上都在Angular区域内运行。
编辑:
带有可观察到的UIService的示例:
@Injectable({ providedIn: 'root'})
export class UiService {
private _drawerState= new BehaviorSubject<void>(null);
isLoading = new Subject<boolean>();
isLoading$ = this.isLoading.pipe(enterZone(this.ngZone));
get drawerState() {
return this._drawerState.asObservable();
}
constructor(private ngZone: NgZone) {}
toggleDrawer() {
this._drawerState.next(null);
}
setIsLoading(value: boolean) {
this.isLoading.next(value);
}
}
答案 1 :(得分:0)
我通过使用ActivityIndicatorComponent中的ChangeDetectorRef对其进行了修复。
在收到新的价值后,我叫changeRef.detectChanges();
的订阅生效了