首页 文章

使用rxjs BehaviorSubject加载微调器

提问于
浏览
2

我为我的 angular 4 应用程序创建了一个加载微调器组件,该组件应该在AJAX调用期间显示但是我无法通过订阅 BehaviorSubject 来显示它 .

这个问题与how to show a spinner till the time data recieved from the server in angular2有关,但不是重复(因为我想用可重复使用的组件做)和Angular 2 + RxJS BehaviorSubject subscribe call not working(虽然我看不出我的代码和接受的答案之间有什么区别 . 我有没有想念?)

我基本上都遵循了这个教程https://hassantariqblog.wordpress.com/2017/03/22/angular2-using-custom-loader-spinner-as-service-in-angular-2-application/

这是我的一些代码:

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);
    }
}

A method in some service that does an AJAX call

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 发生变化就应该调用它 . 为什么不?我究竟做错了什么?

1 回答

  • 3

    问题是由于 LoaderComponent 中的这一行:

    providers: [LoaderService]
    

    通过使用组件级提供程序指定服务,您将通知Angular组件将接收服务的 its own instance . 那不是你想要的;您想要共享模块级实例 .

    只需从 LoaderComponent 中删除该行,以便使用该服务的单个实例 .

相关问题