【问题标题】:Angular BehaviorSubject has delayed update to front-endAngular BehaviorSubject 已延迟更新到前端
【发布时间】:2021-01-31 09:17:46
【问题描述】:

我遇到了一个前端组件没有将更新呈现到BehaviorSubject 的问题,我希望有人能指出我的错误来自哪里。我已经阅读了许多有关 BehaviorSubject 问题的其他问题,但到目前为止我无法找到解决方案。我正在使用 Angular 8 和 Ionic 4。

这里是前端体验:当我第一次导航到组件时,它不会显示任何projectDetails第二次导航到组件,它向我显示了应该第一次显示的projectDetails。 这种“滞后”持续到后续导航

我明白这一定意味着我对.next() 的调用在重新初始化之前不会反映在组件中。

我知道this.s.getProject(this.projectId); 在组件加载时工作正常,因为来自服务的console.log('service fetch complete>>>>>>',this.project.getValue()['name']); 根据当前导航报告了适当的“项目”。但我很难理解为什么这些数据只会在下次打开时传播到组件。

我开始怀疑我在布局方面遗漏了一些东西......

服务

import { Injectable} from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';


@Injectable({
  providedIn: 'root'
})

export class myService {

  private API_URL = 'http://xxx.xxxxx.com/endpoint/';

  private project: BehaviorSubject<any> = new BehaviorSubject({});
  public readonly projectObservable: Observable<Object> = this.project.asObservable();

  constructor(private http:HttpClient) { }

  getProject(projectID:string ){
    console.log('service fetching from>>>>>>>',this.API_URL+projectID);
    this.http.get(this.API_URL+projectID).subscribe(
      (res) => {
        this.project.next(res);
        console.log('service fetch complete>>>>>>',this.project.getValue()['name']);
      }
    );
  }
}

组件

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { myService } from '../../services/myService.service';


@Component({
  selector: 'app-layout',
  templateUrl: './layout.component.html',
  styleUrls: ['./layout.component.scss'],
})
export class LayoutComponent implements OnInit, OnDestroy {
  // Route Paramaters
  private projectTitle: string; 
  private projectId: string;
  // Content Object
  private projectDetails;

  constructor(private route: ActivatedRoute, private s: myService) {
    this.route.params.subscribe(routeParams => console.log("layout.component params", routeParams));
  }

   ngOnInit() {
    this.projectTitle = this.route.snapshot.params.projectTitle;
    this.projectId = this.route.snapshot.params.projectId;

    this.s.getProject(this.projectId);
    this.s.projectObservable.subscribe(prj => this.projectDetails = prj);  
  }

  ngOnDestroy() {
    console.log('hello - layout component destroyed');
  }

}

布局

<ion-card>

  <ion-card-header>
    <ion-card-subtitle>{{projectDetails.type}}</ion-card-subtitle>
    <ion-card-title>{{ projectTitle }}</ion-card-title>
  </ion-card-header>

  <ion-card-content>
    <div markdown ngPreserveWhitespaces>
      {{projectDetails.Narrative}}
    </div>  
  </ion-card-content>

</ion-card>

非常感谢任何帮助!

【问题讨论】:

  • 好吧,我看不出问题出在哪里,但我更喜欢使用异步管道来渲染一个 observable。这很好,因为您的组件将处理取消订阅(您的代码不会这样做!)。异步管道可以这样完成:模板中的 *ngIf="projectDetails$ | async as projectdetails" .. 确保 projectDetails$ 包含可观察对象本身...

标签: angular ionic-framework rxjs rxjs-observables


【解决方案1】:

一个想法:也许在调用 ngOnInit() 之前没有触发路由订阅,所以路由还没有包含你寻找的数据。您可以在 ngOnInit() 中订阅您的路线,并在该订阅中执行现在在您的 ngOnInit() 中的逻辑

【讨论】:

    【解决方案2】:

    问题

    问题出在下面的行this.projectId = this.route.snapshot.params.projectId;。当您第一次访问该页面时,Angular 将加载该组件。当您第二次访问该页面时,angular 会注意到组件没有变化并重用已加载的组件,因此行为

    解决方案

    您需要一种在路由器参数更改时触发更改检测的方法。最简单的方法是在注入的ActivatedRoute 实例上简单地使用paramMap

    在您的 ngOnInit 生命周期挂钩中,将您的代码替换为

      this.route.paramMap.pipe(
        map(params => params.get('projectTitle')),
        tap(projectTitle => this.projectTitle = projectTitle)
      ).subscribe()
      this.route.paramMap.pipe(
        map(params => params.get('projectId')),
        tap(projectId => this.projectId = projectId),
        tap(projectId => this.s.getProject(this.projectId))
      ).subscribe()
      this.s.projectObservable.subscribe(prj => this.projectDetails = prj);  
    

    【讨论】:

      猜你喜欢
      • 2018-08-31
      • 1970-01-01
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-25
      • 2014-06-14
      • 1970-01-01
      相关资源
      最近更新 更多