使用 Behaviorsubject 时不会触发更改检测
Change detection is not triggered when using Behaviorsubject
我有两个同级组件,每个组件都通过正在服务的 Behaviorsubject 进行通信和发送数据。组件 A 在 ngOnInit 内订阅来自组件 B.
的数据
Component B 侦听来自 websoket 的消息,当消息到达时,我正在触发更新 Behaviorsubject value.So 的方法,当新日期从组件 B ,组件 A 必须显示确认模态,但模态未显示,因为即使我使用 angular 变化检测也没有被触发 Object.assign().
我哪里错了?
这是我的代码:
product.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProductService {
subjectProps: any = {
showErrorModal: undefined,
showSuccessfullyModal: undefined,
};
_subject$ = new BehaviorSubject(this.subjectProps);
event = this._subject$.asObservable();
constructor() { }
updateSubjectProps(data: any) {
this._subject$.next(data);
};
}
成功-modal.component.ts
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ProductService } from '../../../services/product-catalogue.service';
@Component({
selector: 'successfully-modal',
templateUrl: './successfully-modal.component.html',
styleUrls: ['./successfully-modal.component.scss']
})
export class ImportCompletedSuccessfullyModalComponent implements OnInit, OnDestroy {
showErrorModal: boolean = false;
showSuccessfullyModal: boolean = false;
productSubscription: Subscription
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.productSubscription = this.productService.event.subscribe(data => {
if (data) {
// Here I need to open successflully confirmation modal
this.showSuccessfullyModal = data.showSuccessfullyModal;
}
});
}
ngOnDestroy(): void {
if (this.productSubscription) {
this.productSubscription.unsubscribe();
}
}
}
products.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ProductService } from './services/product-catalogue.service';
import { Subscription } from 'rxjs';
import { webSocketListener } from '../../../event-bus';
@Component({
selector: 'products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.scss']
})
export class MigrationToolComponent implements OnInit, OnDestroy {
subjectProps: any;
productSubscription: Subscription
isLoading: boolean;
products: any[] = [];
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.fetchProducts();
this.productSubscription = this.productService.event.subscribe(data => {
this.subjectProps = data;
});
webSocketListener.on((message: any) => {
this.checkProductStatus(message);
});
}
fetchProducts(): void {
this.isLoading = true;
this.productService.getProducts().subscribe(res => {
this.isLoading = false;
this.products = res.products;
}),
error => {
this.isLoading = false;
console.log(error);
}
}
checkProductStatus(message: string) {
let subjectProps = Object.assign({}, this.subjectProps);
if (message === 'failed') {
subjectProps.showErrorModal = true;
subjectProps.showSuccessfullyModal = false;
}
if (message === 'success') {
subjectProps.showSuccessfullyModal = true;
subjectProps.showErrorModal = false;
}
this.productService.updateSubjectProps(subjectProps);
this.fetchProducts();
}
ngOnDestroy(): void {
if (this.productSubscription) {
this.productSubscription.unsubscribe();
}
}
}
这与 webSocketListener(可能)在 angular 之外工作有关。您应该在 angular 中调用 checkProductStatus 函数,您可以使用 NgZone service this.
import { Component, OnDestroy, OnInit, NgZone } from '@angular/core';
import { ProductService } from './services/product-catalogue.service';
import { Subscription } from 'rxjs';
import { webSocketListener } from '../../../event-bus';
@Component({
selector: 'products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.scss'],
})
export class MigrationToolComponent implements OnInit, OnDestroy {
constructor(private productService: ProductService, private ngZone: NgZone) {}
ngOnInit(): void {
webSocketListener.on((message: any) => {
this.ngZone.run(() => {
this.checkProductStatus(message);
});
});
}
}
我有两个同级组件,每个组件都通过正在服务的 Behaviorsubject 进行通信和发送数据。组件 A 在 ngOnInit 内订阅来自组件 B.
的数据Component B 侦听来自 websoket 的消息,当消息到达时,我正在触发更新 Behaviorsubject value.So 的方法,当新日期从组件 B ,组件 A 必须显示确认模态,但模态未显示,因为即使我使用 angular 变化检测也没有被触发 Object.assign().
我哪里错了?
这是我的代码:
product.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProductService {
subjectProps: any = {
showErrorModal: undefined,
showSuccessfullyModal: undefined,
};
_subject$ = new BehaviorSubject(this.subjectProps);
event = this._subject$.asObservable();
constructor() { }
updateSubjectProps(data: any) {
this._subject$.next(data);
};
}
成功-modal.component.ts
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ProductService } from '../../../services/product-catalogue.service';
@Component({
selector: 'successfully-modal',
templateUrl: './successfully-modal.component.html',
styleUrls: ['./successfully-modal.component.scss']
})
export class ImportCompletedSuccessfullyModalComponent implements OnInit, OnDestroy {
showErrorModal: boolean = false;
showSuccessfullyModal: boolean = false;
productSubscription: Subscription
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.productSubscription = this.productService.event.subscribe(data => {
if (data) {
// Here I need to open successflully confirmation modal
this.showSuccessfullyModal = data.showSuccessfullyModal;
}
});
}
ngOnDestroy(): void {
if (this.productSubscription) {
this.productSubscription.unsubscribe();
}
}
}
products.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ProductService } from './services/product-catalogue.service';
import { Subscription } from 'rxjs';
import { webSocketListener } from '../../../event-bus';
@Component({
selector: 'products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.scss']
})
export class MigrationToolComponent implements OnInit, OnDestroy {
subjectProps: any;
productSubscription: Subscription
isLoading: boolean;
products: any[] = [];
constructor(private productService: ProductService) { }
ngOnInit(): void {
this.fetchProducts();
this.productSubscription = this.productService.event.subscribe(data => {
this.subjectProps = data;
});
webSocketListener.on((message: any) => {
this.checkProductStatus(message);
});
}
fetchProducts(): void {
this.isLoading = true;
this.productService.getProducts().subscribe(res => {
this.isLoading = false;
this.products = res.products;
}),
error => {
this.isLoading = false;
console.log(error);
}
}
checkProductStatus(message: string) {
let subjectProps = Object.assign({}, this.subjectProps);
if (message === 'failed') {
subjectProps.showErrorModal = true;
subjectProps.showSuccessfullyModal = false;
}
if (message === 'success') {
subjectProps.showSuccessfullyModal = true;
subjectProps.showErrorModal = false;
}
this.productService.updateSubjectProps(subjectProps);
this.fetchProducts();
}
ngOnDestroy(): void {
if (this.productSubscription) {
this.productSubscription.unsubscribe();
}
}
}
这与 webSocketListener(可能)在 angular 之外工作有关。您应该在 angular 中调用 checkProductStatus 函数,您可以使用 NgZone service this.
import { Component, OnDestroy, OnInit, NgZone } from '@angular/core';
import { ProductService } from './services/product-catalogue.service';
import { Subscription } from 'rxjs';
import { webSocketListener } from '../../../event-bus';
@Component({
selector: 'products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.scss'],
})
export class MigrationToolComponent implements OnInit, OnDestroy {
constructor(private productService: ProductService, private ngZone: NgZone) {}
ngOnInit(): void {
webSocketListener.on((message: any) => {
this.ngZone.run(() => {
this.checkProductStatus(message);
});
});
}
}