【问题标题】:.subscribe to BehaviourSubject<any> not firing in Angular 5.subscribe 到 BehaviourSubject<any> 未在 Angular 5 中触发
【发布时间】:2018-04-06 23:32:21
【问题描述】:

我正在尝试订阅我正在编写的服务,以便在更改语言下拉列表时更新mat-autocomplete 输入。

我发现的stackoverflow问题是;

Delegation: EventEmitter or Observable in Angular

但是,当我实现这个时,订阅方法没有触发?我有以下内容;

我的 app.component.ts;

import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { TranslationEmitterService } from '../../services/translation.emitter.service';

@Component({
    selector: 'app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    providers: [ TranslationEmitterService ]
})
export class AppComponent {
    constructor(private translate: TranslateService, private translationService: TranslationEmitterService) {
        translate.addLangs(["en", "pt", "fr"]);
        translate.setDefaultLang('pt');

        let browserLang = translate.getBrowserLang();
        translate.use(browserLang.match(/en|pt|fr/) ? browserLang : 'en');
    }


}

我的组件 html;

<div class="dropdown">
    <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Select Language
    </button>
    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
        <a class="dropdown-item" (click)="switchLanguage('pt')"><span class="flag-icon flag-icon-gr"></span> Portugese</a>
        <a class="dropdown-item" (click)="switchLanguage('en')"><span class="flag-icon flag-icon-gr"></span> English</a>
        <a class="dropdown-item" (click)="switchLanguage('fr')"><span class="flag-icon flag-icon-gr"></span> French</a>
    </div>
</div>

我的可观察服务;

import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class TranslationEmitterService {
    private _languageChangedSource = new BehaviorSubject<any>(0);
    languageChange$ = this._languageChangedSource.asObservable();


    changeLanguage(lang) {
        console.log("in change language " + lang);
        this._languageChangedSource.next(lang);
    }
}

用于切换调用更改的语言的组件;

import { Injectable, Inject, Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

import { TranslationEmitterService } from '../../../services/translation.emitter.service';

@Component({
    selector: 'nav-menu',
    templateUrl: './navmenu.component.html',
    styleUrls: ['./navmenu.component.css']
})
export class NavMenuComponent {
    public isCollapsed = true;
    public status = false;

    constructor(private translate: TranslateService, private translationEmitterService: TranslationEmitterService) {

    }

    public switchLanguage(language: string) {
        console.log("switching language");
        this.translate.use(language);
        this.translationEmitterService.changeLanguage(language);
    }
}

最后我订阅了组件中的事件;

ngOnInit() {

    this.translationSubscription = this.translationService.languageChange$.subscribe(

        // lang => this.refreshAutoCompleteItems(lang)
        x => console.log(x)
    );
}

组件的副本在这里pastebin

没有,当我触发switchLanguage 方法时,我得到输出switching languagein change language fr 输出,但组件观察没有触发?

谁能告诉我我在这里做错了什么?

【问题讨论】:

  • 尝试直接订阅 this.translationService._languageChangedSource。我认为不需要 asObservable 。我已经编写了没有它的代码并且它可以工作。
  • 如果您关心封装,则需要它。您可能只想公开可观察流,但将发射逻辑保留在服务方法的外观后面。
  • 您的代码看起来不错,控制台是否显示任何错误?
  • @Vikas 不,我也看不到任何错误,只是 console.log(x) 没有触发。
  • @Vikas 还要在程序最初运行时添加它确实会触发订阅,因为 x 的值记录为“0”?

标签: angular


【解决方案1】:

问题的一个可能原因是这两个组件中的每一个都有自己的服务实例。当一个组件调用changeLanguage 服务方法时,另一个组件没有收到通知,因为它已经订阅了另一个服务实例。

为确保服务的单个实例由两个组件共享,它应该只提供一次。这可以通过仅在模块级别提供服务并将其从组件的providers 列表中删除来实现:

@NgModule({
    providers: [
        TranslationEmitterService 
    ],
    ...
})
export class AppModule {
}

【讨论】:

    【解决方案2】:

    您需要map您的服务电话。

    this._languageChangedSource.next(lang).map(r=>r.json());
    
    this.translationEmitterService.changeLanguage(language).map(r=>r.json());
    

    当您在组件中使用订阅时,服务中需要地图。

    您的服务还必须返回Observable。你的组件方法可以subscribe.

    【讨论】:

    • 但是我的服务确实返回了一个 observable?即使我在服务上有相关导入,也将map 添加到.next 会引发错误map does not exist on type void
    • 那是因为你的服务没有返回任何东西。它应该返回 Observable。
    • 我没有完全理解你的意思抱歉?服务流是可观察的,也是我订阅的元素。
    【解决方案3】:

    查看下面的演示

    Working Demo

    private _languageChangedSource = new BehaviorSubject<any>(0);
    

    在实例化 BehaviorSubject 时,您已将 0 作为初始值传递。这就是为什么您将初始值设为 0。

    注意 在实例化 BehaviorSubject 时,我们需要给出一个默认值。这是必须的。

    this.switchLanguage("test");
    

    我作为 switchLanguage 函数参数通过了测试,并且得到了以下日志。

    switching language
    in change language test
    test
    

    我希望这能解决您的问题。如果您有任何问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      相关资源
      最近更新 更多