【问题标题】:Angular 6 Subject Subscribe is not workingAngular 6主题订阅不起作用
【发布时间】:2023-03-22 02:36:02
【问题描述】:

我有一个http interceptor,它会在请求开始和结束时发出一个“字符串”:

@Injectable({
  providedIn: 'root'
})
export class LoadingIndicatorService implements HttpInterceptor {

  private loadingIndicatorSource = new  Subject<string>();
  private loadingIndicator$ = this.loadingIndicatorSource.asObservable();

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.updateVisibility('block');
    return next.handle(req)
      .pipe(
        finalize(
          () => {
            this.updateVisibility('none');
          }
        )
      )
      ;
  }

  updateVisibility(state: string) {
    this.loadingIndicatorSource.next(state);
  }

  getLoadingIndicator() {
    return this.loadingIndicator$;
  }
}

这是我注入服务的组件:

export class AppComponent {


  display = 'none';

  constructor(public  authenticationService: AuthenticationService,
              public loadingIndicatorService: LoadingIndicatorService) {
    this.loadingIndicatorService.getLoadingIndicator().subscribe(visibility => {
      console.log(visibility);
      this.display = visibility;
    });

    }
  }

实际上我正在尝试显示加载指示器:

 <div [style.display]="display">
    <mat-progress-bar mode="indeterminate" color="warn" ></mat-progress-bar>
  </div>

我从 Angular 官方网站流出 this 教程。

但是订阅方法永远不会执行。

为什么订阅方法不起作用?

【问题讨论】:

  • 浏览器说:“TypeError:this.loadingIndicator$.next 不是函数”。这是我的进口:import {Observable, Subject} from 'rxjs';
  • 您的代码是this.loadingIndicatorSource.next(state),但您的错误是this.loadingIndicator$.next。请贴出错误代码。
  • 抱歉,还有一条评论,但它已删除,我的评论仍然保留。有人说使用“this.loadingIndicator$.next(state)”,然后他删除了评论。
  • 我会将this.loadingIndicatorService.getLoadingIndicator() 存储在一个变量中并订阅该变量。看起来会好很多。
  • 它不会被触发,因为拦截器需要使用 HTTP 请求。由于您没有创建,因此永远不会调用 next 方法,这意味着您不会运行订阅。

标签: javascript angular typescript observable reactivex


【解决方案1】:

我要做的是创建一个 SpinnerService 和一个 SpinnerInterceptor,而不是将它们合并在一起。

让 spinner 服务分配未完成的请求数量,如果未完成的请求大于 0,则显示 spinner。

@Injectable()
export class SpinnerService {
    private requestAmount$ = new BehaviorSubject(0);

public showSpinner$ = this.requestAmount$.asObservable().pipe(map(r => r > 0));

requestStart() {
    this.requestAmount$.next(this.requestAmount$.getValue() + 1);
}

requestEnd() {
    this.requestAmount$.next(this.requestAmount$.getValue() - 1);
}
}

在您的 spinnerInterceptor 中,您可以注入 SpinnerService 并根据每个请求对其进行更新。

@Injectable()
export class SpinnerInterceptor implements HttpInterceptor {
    constructor(private spinnerService: SpinnerService) {}

intercept(req: HttpRequest<any>, next: HttpHandler) {
        this.spinnerService.requestStart();

        return next.handle(req).pipe(
            finalize(() => {
                this.spinnerService.requestEnd();
            })
        );
    }
}

在您的应用程序组件中使用ngOnInit 挂钩,不要使用违反样式指南的构造函数。

export class AppComponent implements OnInit{


  display = 'none';

  constructor(public  authenticationService: AuthenticationService,
              public spinnerService: SpinnerService) {}
ngOnInit(){
    this.spinnerService.showSpinner$.subscribe(visibility => {
      console.log(visibility);
      this.display = visibility ? 'block': 'none';
    });

    }
  }

分隔使其更易于阅读和理解。

希望这有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-13
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 2017-01-19
    • 1970-01-01
    相关资源
    最近更新 更多