使用 rxjs BehaviorSubject 加载微调器
loading spinner using rxjs BehaviorSubject
我为我的 angular 4 应用程序创建了一个加载微调器组件,它应该在 AJAX 调用期间显示,但我无法通过订阅来显示它一个 BehaviorSubject.
此问题与 but not a duplicate (as I want to do it with a reusable component) and 有关(尽管我没有发现我的代码与已接受的答案有任何区别。我是否遗漏了什么?)
这是我的一些代码:
app.modules.ts
import {AppComponent} from './app.component';
import {AppRoutingModule} from './app-routing.module';
import {SomeComponent} from './some.component';
import {LoaderComponent} from './loader/loader.component';
import {LoaderService} from './loader/loader.service';
@NgModule({
declarations: [
AppComponent,
LoaderComponent,
SomeComponent
],
imports: [
BrowserModule,
NoopAnimationsModule,
AppRoutingModule
],
providers: [
LoaderService
],
bootstrap: [AppComponent]
})
export class AppModule {
}
app.component.html
<router-outlet></router-outlet>
<app-loader></app-loader>
loader.component.html
<div class="loader" *ngIf="isLoading"></div>
loader.component.ts
import {Component, OnInit} from '@angular/core';
import {LoaderService} from './loader.service';
@Component({
selector: 'app-loader',
templateUrl: 'loader.component.html',
providers: [LoaderService]
})
export class LoaderComponent implements OnInit {
isLoading: boolean;
constructor(private loaderService: LoaderService) {
}
ngOnInit() {
this.loaderService.status.subscribe((val: boolean) => {
this.isLoading = val;
});
}
}
loader.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class LoaderService {
public status: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
display(value: boolean) {
console.log('LoaderService.display ' + value);
this.status.next(value);
}
}
某些服务中执行 AJAX 调用的方法
constructor(private http: Http, private loaderService: LoaderService) {
}
getSomeStuff(): Observable<SomeItem[]> {
// show the loading spinner
this.loaderService.display(true);
const content = this.http.get(this.apiUrl)
.map(this.extractData);
content.subscribe(
() => {
// hide the loading spinner
this.loaderService.display(false);
}
);
return content;
}
问题是加载程序从未显示,因为 isLoading
从未设置为 true
。控制台输出:
LoaderComponent subscription false
LoaderService.display true
LoaderService.display false
因此,在初始化组件时,更改 loader.component.ts 中 isLoading
的值的 loaderService 订阅仅被调用一次。但据我了解 BehaviorSubject 应该如何工作,只要 LoaderService.status
发生变化,就应该调用它。为什么不?我做错了什么?
问题是由于 LoaderComponent
中的这一行:
providers: [LoaderService]
通过使用组件级提供程序指定服务,您通知Angular该组件将接收它自己的服务实例。那不是你想要的;你想共享模块级实例。
只需从 LoaderComponent
中删除该行,以便使用该服务的单个实例。
我为我的 angular 4 应用程序创建了一个加载微调器组件,它应该在 AJAX 调用期间显示,但我无法通过订阅来显示它一个 BehaviorSubject.
此问题与
这是我的一些代码:
app.modules.ts
import {AppComponent} from './app.component';
import {AppRoutingModule} from './app-routing.module';
import {SomeComponent} from './some.component';
import {LoaderComponent} from './loader/loader.component';
import {LoaderService} from './loader/loader.service';
@NgModule({
declarations: [
AppComponent,
LoaderComponent,
SomeComponent
],
imports: [
BrowserModule,
NoopAnimationsModule,
AppRoutingModule
],
providers: [
LoaderService
],
bootstrap: [AppComponent]
})
export class AppModule {
}
app.component.html
<router-outlet></router-outlet>
<app-loader></app-loader>
loader.component.html
<div class="loader" *ngIf="isLoading"></div>
loader.component.ts
import {Component, OnInit} from '@angular/core';
import {LoaderService} from './loader.service';
@Component({
selector: 'app-loader',
templateUrl: 'loader.component.html',
providers: [LoaderService]
})
export class LoaderComponent implements OnInit {
isLoading: boolean;
constructor(private loaderService: LoaderService) {
}
ngOnInit() {
this.loaderService.status.subscribe((val: boolean) => {
this.isLoading = val;
});
}
}
loader.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class LoaderService {
public status: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
display(value: boolean) {
console.log('LoaderService.display ' + value);
this.status.next(value);
}
}
某些服务中执行 AJAX 调用的方法
constructor(private http: Http, private loaderService: LoaderService) {
}
getSomeStuff(): Observable<SomeItem[]> {
// show the loading spinner
this.loaderService.display(true);
const content = this.http.get(this.apiUrl)
.map(this.extractData);
content.subscribe(
() => {
// hide the loading spinner
this.loaderService.display(false);
}
);
return content;
}
问题是加载程序从未显示,因为 isLoading
从未设置为 true
。控制台输出:
LoaderComponent subscription false
LoaderService.display true
LoaderService.display false
因此,在初始化组件时,更改 loader.component.ts 中 isLoading
的值的 loaderService 订阅仅被调用一次。但据我了解 BehaviorSubject 应该如何工作,只要 LoaderService.status
发生变化,就应该调用它。为什么不?我做错了什么?
问题是由于 LoaderComponent
中的这一行:
providers: [LoaderService]
通过使用组件级提供程序指定服务,您通知Angular该组件将接收它自己的服务实例。那不是你想要的;你想共享模块级实例。
只需从 LoaderComponent
中删除该行,以便使用该服务的单个实例。