简体   繁体   English

Angular 2:可观察/订阅未触发

[英]Angular 2: Observable / Subscription not triggering

I have done this multiple times in my App.我在我的应用程序中多次这样做了。 It's simple, it should work... But this time it doesn't.很简单,它应该可以工作……但这次不行。

My issue:我的问题:

I am calling a method in a service from a Component A, my Component B is subscribed but doesn't react nor receive anything.我正在从组件 A 调用服务中的方法,我的组件 B 已订阅但没有反应也没有收到任何东西。 subscribe() is not triggering! subscribe()没有触发!

navigation-elements.service.ts导航元素.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 IboDetailsGeneral组件

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

This component triggers the service's method: updateIBOsNavigation .此组件触发服务的方法: updateIBOsNavigation

IBOsNavigationElement component IBOsNavigationElement组件

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

This component is subscribed, it should listed and receive the data...此组件已订阅,它应该列出并接收数据...

Let's sort out DI: Take into account that IboDetailsGeneral is in a lower layer on the App's structure, so IboDetailsGeneral is child of IBOsNavigationElement .让我们梳理一下 DI:考虑到IboDetailsGeneral位于应用程序结构的较低层,因此IboDetailsGeneralIboDetailsGeneralIBOsNavigationElement

This is why I add NavigationElementsService into IBOsNavigationElement 's module:这就是我将NavigationElementsService添加到IBOsNavigationElement的模块的原因:

NavigationModule is IBOsNavigationElement 's module NavigationModuleIBOsNavigationElement的模块

@NgModule({
    imports: [
        // A lot of stuff
    ],
    declarations: [
        // A lot of stuff
        IBOsNavigationElement
    ],
    exports: [
        // A lot of stuff
    ],
    providers: [
        NavigationElementsService
    ]
})

Console:安慰:

CALLING updateIBOsNavigation FUNCTION调用更新IBOsNavigation FUNCTION

updateIBOsNavigation "95"更新IBOsNavigation "95"

CALLING updateIBOsNavigation FUNCTION AGAIN再次调用更新IBOs导航功能

updateIBOsNavigation "test"更新IBOsNavigation“测试”

This console results tells me that:这个控制台结果告诉我:

  • The method is being called, so no provider error.正在调用该方法,因此没有提供程序错误。 Communication with service is OK .与服务的沟通是可以的

My tests:我的测试:

  • I have tried calling a random method in IBOsNavigationElement (the listener) , and communication with service is good.我曾尝试在IBOsNavigationElement (侦听器)中调用随机方法,并且与服务的通信良好。
  • The only place where NavigationElementsService is added to providers is in NavigationModule , so there is only one instance of the service right? NavigationElementsService添加到providers的唯一地方是在NavigationModule ,所以只有一个服务实例,对吗? Then, the issue explained in the following link doesn't take place: Angular 2 observable subscription not triggering然后,以下链接中解释的问题不会发生: Angular 2 observable subscription not triggering

I am really sorry for my 'wall of text' but at this point I am kind of desperate.我真的很抱歉我的“文字墙”,但在这一点上我有点绝望。

Any help is appretiated, thank you!任何帮助表示赞赏,谢谢!

Update 1:更新 1:

After the first answer I have tried several things...在第一个答案之后,我尝试了几件事......

Using ReplaySubject :使用ReplaySubject

@Injectable()
export class NavigationElementsService {
    public updateIBOsNavigation$ = new ReplaySubject();

    updateIBOsNavigation(navigationData) {
        log.d('updateIBOsNavigation', JSON.stringify(navigationData));
        this.updateIBOsNavigation$.next(navigationData);
    }
}

Result: When calling updateIBOsNavigation() , subscribe() is still not triggering.结果:调用updateIBOsNavigation()subscribe()仍未触发。

Using BehaviorSubject :使用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);
    }
}

Result: It enters subscribe() on initialization but when I call updateIBOsNavigation() , subscribe() is still not triggering.结果:它在初始化时进入subscribe()但当我调用updateIBOsNavigation()subscribe()仍然没有触发。

Using BehaviorSubject v2:使用BehaviorSubject v2:

I tried this approach: behaviourSubject in angular2 , how it works and how to use it我尝试了这种方法: angular2 中的 behaviorSubject ,它是如何工作的以及如何使用它

@Injectable()
export class NavigationElementsService {
    public updateIBOsNavigation$: Subject<string> = new BehaviorSubject<string>(null);

    updateIBOsNavigation(navigationData) {
        log.d('updateIBOsNavigation', JSON.stringify(navigationData));
        this.updateIBOsNavigation$.next(navigationData);
    }
}

Result: Same as previous application of BehaviorSubject .结果:与之前的BehaviorSubject应用程序相同。

Update 2:更新 2:

More samples of desperate attempts after researching throughout the web...在整个网络上进行研究后,更多绝望的尝试样本......

Using BehaviorSubject v3:使用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);
    }
}

Result: Same as previous BehaviorSubject attempts... Desperation is rising...结果:与之前的BehaviorSubject尝试相同……绝望正在上升……

Update 3:更新 3:

Just in case, I wanted to make sure that NavigationElementsService is a singleton :以防万一,我想确保NavigationElementsService是一个单例

export class NavigationModule {
    static forRoot() {
        return {
            ngModule: NavigationModule,
            providers: [NavigationElementsService]
        };
    }
}

And when importing:导入时:

imports: [
        NavigationModule.forRoot()
       ]

Result: Same issue as always, subscribe() not triggering, but at least I know that there is one instance of NavigationElementsService .结果:与往常一样的问题, subscribe()没有触发,但至少我知道有一个NavigationElementsService实例。

I think the issue is your Subject type With Subject , any component that subscribes after an event has fired will NOT receive a value.我认为问题在于您的Subject类型 With Subject ,在事件触发后订阅的任何组件都不会收到值。 To replay the previous value to late subscribers use BehaviorSubject or ReplaySubject instead of Subject .要将先前的值重播给迟到的订阅者,请使用BehaviorSubjectReplaySubject而不是Subject

More on different Subject types from http://reactivex.io/documentation/subject.html更多关于不同主题类型的信息来自http://reactivex.io/documentation/subject.html

Behavior Subject行为主体

When an observer subscribes to a BehaviorSubject, it begins by emitting the item most recently emitted by the source Observable (or a seed/default value if none has yet been emitted) and then continues to emit any other items emitted later by the source Observable(s).当观察者订阅 BehaviorSubject 时,它首先发射源 Observable 最近发射的项目(如果尚未发射,则为种子/默认值),然后继续发射源 Observable 稍后发射的任何其他项目( s)。

ReplaySubject重播主题

ReplaySubject emits to any observer all of the items that were emitted by the source Observable(s), regardless of when the observer subscribes. ReplaySubject 将源 Observable(s) 发出的所有项目发送给任何观察者,而不管观察者何时订阅。

A BehaviorSubject does require a default value when setting it up. BehaviorSubject在设置时确实需要一个默认值。 So you'd need to create it with some sort of value:所以你需要用某种价值来创造它:

updateIBOsNavigationSubject = new BehaviorSubject<any>('');
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();

updateIBOsNavigation(navigationData) {
    log.d('updateIBOsNavigation', JSON.stringify(navigationData));
    this.updateIBOsNavigationSubject.next(navigationData);
}

A ReplaySubject does not require a default value. ReplaySubject不需要默认值。

EDIT编辑

When using a shared service it is also important to make sure the service is being provided ONLY at the root module.使用共享服务时,确保仅在根模块中提供服务也很重要。 If it is provided multiple places, then the components may not be getting the same instance.如果它提供了多个位置,则组件可能不会获得相同的实例。 Even if the service is provided at the root level, if a module between the root level and your component provides the service, a new instance will get sent down that branch of the Dependency Injection tree.即使服务是在根级别提供的,如果根级别和您的组件之间的模块提供服务,一个新的实例将被发送到依赖注入树的那个分支。

Hope this helps.希望这可以帮助。

When we include a service in 'providers', then it is instantiated and this state is maintained between its component as well as its child components.当我们在 'providers' 中包含一个服务时,它会被实例化,并且这个状态在它的组件和它的子组件之间保持。

And, if we include the service in both components provider array, then it is no more following singleton.而且,如果我们将服务包含在两个组件提供者数组中,那么它就不再是单例了。 The state will be independent and not shared between them.状态将是独立的,不会在它们之间共享。

So, include your service only at parent component or your root component.因此,仅在父组件或根组件中包含您的服务。

I too faced this issue and solved with help of this solution here, https://stackoverflow.com/a/38034298/5730167 .我也遇到了这个问题,并在此解决方案的帮助下解决了这个问题, https://stackoverflow.com/a/38034298/5730167

In my case I was using the same service at parent module "app.module" and in child module as well.就我而言,我在父模块“app.module”和子模块中使用了相同的服务。 I Removed Service from Provider section in Child Module.我从子模块中的 Provider 部分删除了服务。 It Worked.有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM