我使用来自Rxjs的Observables和Subjects来在两个组件之间进行通信,这是服务部分:
import {
Injectable,
EventEmitter,
Output
} from '@angular/core';
import {
HttpClientModule,
HttpClient
} from '@angular/common/http';
import {
Observable
} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import {
Subject
} from 'rxjs/Subject';
import {
AppConstants
} from './../config/constants';
@Injectable()
export class GlobalService {
private subject = new Subject < any > ();
@Output() LoggedIn: EventEmitter < any > = new EventEmitter();
mfaData: any;
constructor(private http: HttpClient) {
}
validateCreds(postData, institutionId, customerId) {
return this.http.post(AppConstants.baseUrl + AppConstants.serverRoutes.validateCreds + institutionId + '/' + customerId, postData)
.subscribe(response => {
console.log(response);
if (response['status'] == 203) {
this.mfaData = response['body'].questions;
if (this.mfaData[0].choices || this.mfaData[0].imageChoices) {
console.log('hey there');
this.subject.next({
mfaData: JSON.stringify(this.mfaData)
});
}
}
})
}
refreshHeaders(): Observable < any > {
return this.subject.asObservable();
}
}
&#13;
import {
Subscription
} from 'rxjs/Subscription';
import {
GlobalService
} from '../../../providers/global.serivce';
export class MfaChallengeComponent implements OnInit {
subscription: Subscription;
constructor(private activatedRoute: ActivatedRoute, private bankService: BanksService, private globalService: GlobalService) {
this.subscription = this.globalService.refreshHeaders().subscribe(message => {
console.log(message);
});
}
}
&#13;
但是当我从后端收到数据时,我调用了主题的下一个方法,并在另一个组件的构造函数中再次调用它。它不起作用,而我看到它的工作实例。该服务已在全球注入。
答案 0 :(得分:4)
我担心你误解了RxJS的一些核心概念。在RxJS中,受试者是热的可观察者。无论是否有人在听,热的观察者都会发出事件。 (查看此文章了解更多信息https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html)。
因此,假设在您的服务中,您执行后端呼叫,您可以通过主题“管道”该呼叫的结果。 稍后在代码中,您的组件已启动,构造函数已执行,您开始收听主题。不幸的是,你通过这个主题的事件已经过去了。
要解决此问题,您可以使用ReplaySubject(1)更改主题。如果我没有弄错的话,那应该可以解决问题。
但是您的代码还有其他一些问题。你通过一个主题管道结果的事实在这里是不必要的。如果我查看你的代码,我想你想做一次后端调用,然后缓存结果。这个名为shareReplay
的特定运算符。使用它,您的代码将如下所示:
export class GlobalService {
cachedObservable$;
@Output() LoggedIn: EventEmitter < any > = new EventEmitter();
mfaData: any;
constructor(private http: HttpClient) {
}
validateCreds(postData, institutionId, customerId) {
this.cachedObservable$ = this.http.post(AppConstants.baseUrl + AppConstants.serverRoutes.validateCreds + institutionId + '/' + customerId, postData)
.map(response => {
if (response['status'] == 203) {
this.mfaData = response['body'].questions;
if (this.mfaData[0].choices || this.mfaData[0].imageChoices) {
return {
mfaData: JSON.stringify(this.mfaData)
};
}
}
})
.shareReplay(1);
}
refreshHeaders(): Observable < any > {
return this.cachedObservable$;
}
}
您正在创建一个将被执行一次的observable,之后的结果将被缓存。您应尽量避免在服务和主题中使用订阅。
要了解有关shareReplay
的更多信息,请查看有关RxJS中多播运营商的博文,我写道:https://blog.kwintenp.com/multicasting-operators-in-rxjs