私はアプリでこれを複数回行いました。簡単で、動作するはずです...しかし、今回は動作しません。
私の問題:
コンポーネントAからサービスのメソッドを呼び出しています。コンポーネントBはサブスクライブされていますが、反応も受信もしません。 subscribe()
はトリガーしていません!
navigation-elements.service.ts
_@Injectable()
export class NavigationElementsService {
updateIBOsNavigation$: Observable<any>;
private updateIBOsNavigationSubject = new Subject<any>();
constructor() {
this.updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
}
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
}
_
IboDetailsGeneral
component
_export class IboDetailsGeneral implements OnInit, OnDestroy {
id: string;
private sub: any;
constructor(private route: ActivatedRoute, private iboService: IBOsService, private navigationService: NavigationElementsService) {
this.sub = this.route.params.subscribe(params => {
this.id = params['id'];
console.log('CALLING updateIBOsNavigation FUNCTION');
this.navigationService.updateIBOsNavigation(this.id);
});
}
ngOnInit() {
console.log('CALLING updateIBOsNavigation FUNCTION AGAIN');
this.navigationService.updateIBOsNavigation('test');
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
_
このコンポーネントは、サービスのメソッドupdateIBOsNavigation
をトリガーします。
IBOsNavigationElement
component
_export class IBOsNavigationElement implements OnInit {
private id: string;
constructor(private navigationService: NavigationElementsService) {
this.navigationService.updateIBOsNavigation$.subscribe((navigationData) => {
log.d('I received this Navigation Data:', JSON.stringify(navigationData));
this.id = navigationData;
}
);
}
ngOnInit() {
}
}
_
このコンポーネントはサブスクライブされており、データをリストして受信する必要があります...
DIを整理しましょう:IboDetailsGeneral
はアプリの構造の下位層にあるため、IboDetailsGeneral
はchildのIBOsNavigationElement
。
NavigationElementsService
のモジュールにIBOsNavigationElement
を追加する理由は次のとおりです。
NavigationModule
はIBOsNavigationElement
のモジュールです
_@NgModule({
imports: [
// A lot of stuff
],
declarations: [
// A lot of stuff
IBOsNavigationElement
],
exports: [
// A lot of stuff
],
providers: [
NavigationElementsService
]
})
_
コンソール:
CALLING updateIBOsNavigation FUNCTION
updateIBOsNavigation "95"
CALLING updateIBOsNavigation Function AGAIN
updateIBOsNavigation「テスト」
このコンソールの結果から次のことがわかります。
私のテスト:
IBOsNavigationElement
(リスナー)でランダムメソッドを呼び出してみましたが、サービスとの通信は良好です。NavigationElementsService
にproviders
が追加される唯一の場所はNavigationModule
にあるため、サービスのインスタンスは1つだけです。その後、次のリンクで説明されている問題は発生しません: Angular 2 observable subscription not triggering私は 'テキストの壁'に本当に申し訳ありませんが、この時点で私はちょっと必死です。
どんな助けも感謝します、ありがとう!
更新1:
最初の答えの後、私はいくつかのことを試しました...
ReplaySubject
:の使用
_@Injectable()
export class NavigationElementsService {
public updateIBOsNavigation$ = new ReplaySubject();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigation$.next(navigationData);
}
}
_
結果:updateIBOsNavigation()
を呼び出すとき、subscribe()
はまだトリガーしていません。
BehaviorSubject
:の使用
_@Injectable()
export class NavigationElementsService {
updateIBOsNavigationSubject = new BehaviorSubject<any>('');
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
}
_
結果:初期化時にsubscribe()
に入りますが、updateIBOsNavigation()
を呼び出すと、subscribe()
はまだトリガーされません。
BehaviorSubject
v2を使用:
私はこのアプローチを試しました: behaviourSubject in angle2、それがどのように機能し、どのように使用するか
_@Injectable()
export class NavigationElementsService {
public updateIBOsNavigation$: Subject<string> = new BehaviorSubject<string>(null);
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigation$.next(navigationData);
}
}
_
結果:以前のBehaviorSubject
の適用と同じ。
更新2:
ウェブ全体を調査した後の必死の試みのサンプル.
BehaviorSubject
v3を使用:
_@Injectable()
export class NavigationElementsService {
updateIBOsNavigation$: Observable<any>;
updateIBOsNavigationSubject = <BehaviorSubject<any>> new BehaviorSubject([]);
constructor() {
this.updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
}
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation()', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
}
_
結果:前のBehaviorSubject
試行と同じ...絶望が高まっています...
更新3:
念のため、NavigationElementsService
がsingletonであることを確認したかった:
_export class NavigationModule {
static forRoot() {
return {
ngModule: NavigationModule,
providers: [NavigationElementsService]
};
}
}
_
そしてインポートするとき:
_imports: [
NavigationModule.forRoot()
]
_
結果:いつもと同じ問題、subscribe()
はトリガーしませんが、少なくともNavigationElementsService
のインスタンスが1つあることは知っています。
問題はあなたのSubject
タイプだと思いますSubject
では、イベントが発生した後にサブスクライブするコンポーネントは値を受け取りません。前の値を遅いサブスクライバにリプレイするには、BehaviorSubject
の代わりにReplaySubject
またはSubject
を使用します。
http://reactivex.io/documentation/subject.html のさまざまなサブジェクトタイプの詳細
行動主題
オブザーバーがBehaviorSubjectにサブスクライブすると、ソースObservableによって最後に放出されたアイテム(またはまだ放出されていない場合はシード/デフォルト値)の放出から始まり、ソースObservableによって後で放出された他のアイテムの放出を続けます( s)。
ReplaySubject
ReplaySubjectは、オブザーバーがサブスクライブする時期に関係なく、ソースObservableによって発行されたすべてのアイテムを任意のオブザーバーに発行します。
BehaviorSubject
は、セットアップ時にデフォルト値を必要とします。そのため、何らかの値で作成する必要があります。
updateIBOsNavigationSubject = new BehaviorSubject<any>('');
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
ReplaySubject
はデフォルト値を必要としません。
[〜#〜] edit [〜#〜]
共有サービスを使用する場合、ルートモジュールでのみサービスが提供されるようにすることも重要です。複数の場所で提供される場合、コンポーネントは同じインスタンスを取得していない可能性があります。サービスがルートレベルで提供される場合でも、ルートレベルとコンポーネントの間のモジュールがサービスを提供する場合、新しいインスタンスが依存性注入ツリーのそのブランチに送信されます。
お役に立てれば。
「プロバイダー」にサービスを含めると、インスタンス化され、コンポーネントと子コンポーネントの間でこの状態が維持されます。
そして、両方のコンポーネントプロバイダー配列にサービスを含めると、シングルトンに続くことはなくなります。状態は独立しており、それらの間で共有されません。
そのため、親コンポーネントまたはルートコンポーネントのみにサービスを含めてください。
私もこの問題に直面し、このソリューションの助けを借りて解決しました https://stackoverflow.com/a/38034298/5730167 。