当我在BehaviourSubject上调用函数时,未触发订阅函数

时间:2019-11-26 13:23:33

标签: angular angular8 angular-services angular-module

我有2个组件,并且在这2个组件之间共享一项服务,比方说ComponentA和ComponentB。应用程序工具栏(组件A)中的一个组件和组件B中的另一个组件通过路由模块进行路由。这是HTML:

<a></a>
<router-outlet></router-outlet>

之所以这样,是因为我想始终将工具栏固定在顶部。 在组件A的HTML中,我可以选择应用程序的语言。在组件BI中,某些内容来自后端,具体取决于所选语言。我希望当用户更改语言时,内容来自服务器以进行呈现。我正在使用服务来调用后端并呈现新内容。我的问题来了,对服务器的调用已经完成并且可以,但是它从未进入订阅功能。我尝试使用共享模块(带有或不带有forRoot()),尝试使服务成为模块的提供程序,然后将模块(AppRoutingModule)导入另一个模块(AppModule)中。在这一刻,我到达了“没有服务提供者”的地步。控制台错误。服务和组件的代码: 服务:

@Injectable()
export class SharedService extends GlobalHttpService<HomeSection> {
  private sectionsSubject: BehaviorSubject<HomeSection[]>;
  constructor(private http: HttpClient) {
    super("api/path", new GlobalSerializer(HomeSection), http);
    this.sectionsSubject = new BehaviorSubject<HomeSection[]>([]);
  }

  load() {
    this.list().subscribe(res => {
      this.sectionsSubject.next(res);
    });
  }
  get content() {
    return this.sectionsSubject.asObservable();
  }
}

AppModule

@NgModule({
 imports:[AppRoutingModule]
})
export class AppModule {}

AppRoutingModule

export function SharedServiceFactory(http: HttpClient){
  return new SharedServiceFactory(http);
}

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [
    {
      provide: SectionService,
      useFactory: SectionServiceFactory,
      deps: [HttpClient]
    }
  ]
})
export class AppRoutingModule {}

组件A:

@Component({
  selector: "a",
  templateUrl: ".a.component.html",
  styleUrls: ["./a.component.scss"]
})
export class AComponent implements OnInit {
  constructor(
    public authentificationService: AuthenticationService,
    private languagesService: LanguagesService,
    private sharedService: SharedService
  ) {
  }
 ngOnInit() {
//other logic;
}

updateLanguage(event) {
// other logic;
this.sharedService.load();
}

ComponentB

@Component({
  selector: "app-b",
  templateUrl: "./b.component.html",
  styleUrls: ["./b.component.scss"]
})
export class BComponent implements OnInit {
  constructor(
    private sharedService: SharedService,
  ) {}

ngOnInit() {
 this.sharedService.load();
 this.sharedService.content.subscribe(s => {
 // logic
 });
}

如何使SharedService具有单个实例,或者可以将一个模块包含在另一个模块中?

2 个答案:

答案 0 :(得分:0)

尝试在您的服务中执行此操作:

@Injectable({ providedIn: 'root' })

并从 AppRoutingModule 中删除此服务的提供。 如果您使用providedIn: 'root',则无需在其他地方提供它。它将在Angular树的顶部注入服务,因此您将始终拥有相同的实例。它的另一个好处-它使服务可以摇树。

答案 1 :(得分:0)

首先将服务导入AppModule:

AppModule

@NgModule({
 imports:[AppRoutingModule],
 providers: [SharedService]
})
export class AppModule {}

OR:

@Injectable({提供者:'root'}) 导出类SharedService扩展了GlobalHttpService { ... }

然后,您不必在SharedService中创建方法来返回Observable事件,只需在构造函数中创建一次属性和实例即可。

SharedService

@Injectable()
export class SharedService extends GlobalHttpService<HomeSection> {
  private sectionsSubject: BehaviorSubject<HomeSection[]>;
  public content$: Observable<HomeSection[]>;
  constructor(private http: HttpClient) {
    super("api/path", new GlobalSerializer(HomeSection), http);
    this.sectionsSubject = new BehaviorSubject<HomeSection[]>([]);
    this.content$ = this.sectionsSubject.asObservable();
  }

  load() {
    this.list().subscribe(res => {
      this.sectionsSubject.next(res);
    });
  }
}

最后在组件B中:

@Component({
  selector: "app-b",
  templateUrl: "./b.component.html",
  styleUrls: ["./b.component.scss"]
})
export class BComponent implements OnInit {
  constructor(
    private sharedService: SharedService,
  ) {}

ngOnInit() {
 this.sharedService.load();
 this.sharedService.content$.subscribe(s => {
     // logic
 });
}