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