0

我用的观测量和主语Rxjs两个组件之间的通信,这是服务的一部分:如何使用观测量的组件间通信

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(); 
 
    } 
 

 

 

 

 

 
}
和我打电话从用户另一部件的构造的,该片段是:

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); 
 
    }); 
 
    } 
 
}

但是,当我从后端接收数据时,我会调用主题的下一个方法,并在另一个组件的构造函数中再次调用它。它不起作用,而我见过它的例子。该服务已被全球注入。

+0

下面已经有一个非常好的解释。我只是补充一点,从角度来看,'constructor'很少是一个调用服务的好地方。 'ngOnInit()'通常是应该发生的事情。 –

回答

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$; 
 
    } 
 
}

你正在创建一个可观察的,将被执行一次,结果随后将被缓存。你应该尽量避免使用订阅服务和主题尽可能。 要了解有关shareReplay的更多信息,请查看关于RxJS中多播运营商的博文。我写道:https://blog.kwintenp.com/multicasting-operators-in-rxjs

+0

嘿我试了一下有些变化的代码,它开始工作,但是这里又一次出现的问题是,当我通过主题下一个方法传递数据时,订阅被调用并且它监听事件。但是,当调用具有侦听器功能的相同组件时,我不会收到数据。 – Raghav