角度2:可观察/订阅未触发 [英] Angular 2: Observable / Subscription not triggering

查看:55
本文介绍了角度2:可观察/订阅未触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在我的App中多次进行了此操作.很简单,它应该可以工作...但是这次没有.

I have done this multiple times in my App. It's simple, it should work... But this time it doesn't.

我的问题:

我正在从组件A调用服务中的方法,我的组件B已订阅,但不响应也不接收任何内容. subscribe()没有触发!

I am calling a method in a service from a Component A, my Component B is subscribed but doesn't react nor receive anything. subscribe() is not triggering!

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组件

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.

This component triggers the service's method: updateIBOsNavigation.

IBOsNavigationElement组件

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

该组件已订阅,应该列出并接收数据...

This component is subscribed, it should listed and receive the data...

让我们整理一下DI: 考虑到IboDetailsGeneral位于应用程序结构的下层,因此IboDetailsGeneralIBOsNavigationElement child .

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.

这就是为什么我将NavigationElementsService添加到IBOsNavigationElement的模块中的原因:

This is why I add NavigationElementsService into IBOsNavigationElement's module:

NavigationModuleIBOsNavigationElement的模块

NavigationModule is IBOsNavigationElement's module

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

控制台:

调用updateIBOsNavigation功能

CALLING updateIBOsNavigation FUNCTION

updateIBOsNavigation"95"

updateIBOsNavigation "95"

再次致电更新IBOsNavigation功能

CALLING updateIBOsNavigation FUNCTION AGAIN

updateIBOsNavigation测试"

updateIBOsNavigation "test"

此控制台结果告诉我:

  • 该方法正在被调用,因此没有提供程序错误. 可以与服务进行通信.

我的测试:

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

我真的很抱歉我的文字墙" ,但在这一点上,我感到很绝望.

I am really sorry for my 'wall of text' but at this point I am kind of desperate.

感谢您的帮助,谢谢!

更新1:

在第一个答案之后,我尝试了几件事...

After the first answer I have tried several things...

使用ReplaySubject:

Using ReplaySubject:

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

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

结果:调用updateIBOsNavigation()时,subscribe()仍未触发.

Result: When calling updateIBOsNavigation(), subscribe() is still not triggering.

使用BehaviorSubject:

Using 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()仍未触发.

Result: It enters subscribe() on initialization but when I call updateIBOsNavigation(), subscribe() is still not triggering.

使用BehaviorSubject v2:

Using BehaviorSubject v2:

我尝试了这种方法: behaviourSubject angular2,它如何工作以及如何使用

@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的先前应用相同.

Result: Same as previous application of BehaviorSubject.

更新2:

在整个网络上进行搜索后,更多绝望尝试的示例...

More samples of desperate attempts after researching throughout the web...

使用BehaviorSubject v3:

Using 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尝试相同...绝望情绪正在上升...

Result: Same as previous BehaviorSubject attempts... Desperation is rising...

更新3:

以防万一,我想确保NavigationElementsService singleton :

Just in case, I wanted to make sure that NavigationElementsService is a singleton:

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

导入时:

imports: [
        NavigationModule.forRoot()
       ]

结果:与往常一样,subscribe()没有触发,但至少我知道有一个NavigationElementsService实例.

Result: Same issue as always, subscribe() not triggering, but at least I know that there is one instance of NavigationElementsService.

推荐答案

我认为问题是您的Subject类型使用Subject时,在事件触发后进行预订的任何组件都不会收到值.要将先前的值重播给后期订阅者,请使用BehaviorSubjectReplaySubject而不是Subject.

I think the issue is your Subject type With Subject, any component that subscribes after an event has fired will NOT receive a value. To replay the previous value to late subscribers use BehaviorSubject or ReplaySubject instead of Subject.

有关 http://reactivex.io/documentation/subject.html

行为主题

当观察者订阅一个BehaviorSubject时,它首先发出源Observable最近发出的项目(如果尚未发出,则为种子/默认值),然后继续发出后来由该Observable发出的任何其他项目.源可观察到的.

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).

ReplaySubject

ReplaySubject向观察者发出源Observable发出的所有项目,无论观察者何时订阅.

ReplaySubject emits to any observer all of the items that were emitted by the source Observable(s), regardless of when the observer subscribes.

BehaviorSubject设置时确实需要默认值.因此,您需要使用某种值来创建它:

A BehaviorSubject does require a default value when setting it up. 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);
}

ReplaySubject不需要默认值.

编辑

使用共享服务时,确保仅在根模块上提供该服务也很重要.如果提供了多个位置,则组件可能不会获得相同的实例.即使该服务是在根级别提供的,但如果根级别和您的组件之间的模块提供了该服务,则新实例将在依赖注入树的该分支下发送.

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.

希望这会有所帮助.

这篇关于角度2:可观察/订阅未触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆