繁体   English   中英

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

[英]Angular 2: Observable / Subscription not triggering

我在我的应用程序中多次这样做了。 很简单,它应该可以工作……但这次不行。

我的问题:

我正在从组件 A 调用服务中的方法,我的组件 B 已订阅但没有反应也没有收到任何东西。 subscribe()没有触发!

导航元素.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组件

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

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位于应用程序结构的较低层,因此IboDetailsGeneralIboDetailsGeneralIBOsNavigationElement

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

NavigationModuleIBOsNavigationElement的模块

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

安慰:

调用更新IBOsNavigation FUNCTION

更新IBOsNavigation "95"

再次调用更新IBOs导航功能

更新IBOsNavigation“测试”

这个控制台结果告诉我:

  • 正在调用该方法,因此没有提供程序错误。 与服务的沟通是可以的

我的测试:

  • 我曾尝试在IBOsNavigationElement (侦听器)中调用随机方法,并且与服务的通信良好。
  • NavigationElementsService添加到providers的唯一地方是在NavigationModule ,所以只有一个服务实例,对吗? 然后,以下链接中解释的问题不会发生: 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:

我尝试了这种方法: 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);
    }
}

结果:与之前的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是一个单例

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

导入时:

imports: [
        NavigationModule.forRoot()
       ]

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

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

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

行为主体

当观察者订阅 BehaviorSubject 时,它首先发射源 Observable 最近发射的项目(如果尚未发射,则为种子/默认值),然后继续发射源 Observable 稍后发射的任何其他项目( s)。

重播主题

ReplaySubject 将源 Observable(s) 发出的所有项目发送给任何观察者,而不管观察者何时订阅。

BehaviorSubject在设置时确实需要一个默认值。 所以你需要用某种价值来创造它:

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

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

ReplaySubject不需要默认值。

编辑

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

希望这可以帮助。

当我们在 'providers' 中包含一个服务时,它会被实例化,并且这个状态在它的组件和它的子组件之间保持。

而且,如果我们将服务包含在两个组件提供者数组中,那么它就不再是单例了。 状态将是独立的,不会在它们之间共享。

因此,仅在父组件或根组件中包含您的服务。

我也遇到了这个问题,并在此解决方案的帮助下解决了这个问题, https://stackoverflow.com/a/38034298/5730167

就我而言,我在父模块“app.module”和子模块中使用了相同的服务。 我从子模块中的 Provider 部分删除了服务。 有效。

暂无
暂无

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

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