【问题标题】:observable undefinded in facade architeture with rxjs使用 rxjs 在外观架构中可观察到未定义
【发布时间】:2021-11-22 08:41:12
【问题描述】:

(根据建议,我正在编辑我的问题) @Gunnar.B

与 api 连接的服务

@Injectable({
  providedIn: 'root'
})
export class ConsolidadoApi {
  constructor(private http: HttpClient) { }
  getInvestiments(search?: any): Observable<any> {
    return this.http.get<any>(`${environment.basePosicaoConsolidada}`);
  }
}

此服务(层)为表示层(组件)中的组件公开状态流和接口

@Injectable({
    providedIn: 'root'
})
export class CoreService {

    constructor(private api: ConsolidadoApi, private state: StateService) { }

    public getInvestments$(): Observable<any> {
        return this.state.getInvestiments$()
    }

    public loadInvestments() {
        return this.api.getInvestiments()
        .pipe(
            tap(investPortifolio => this.state.setInvestments(investPortifolio))
        );
    }
}

此服务负责将转到组件的逻辑

@Injectable({
  providedIn: 'root'
})
export class StateService {

  private investments$ = new BehaviorSubject<any>(null);

  public getInvestiments$() {
    return this.investments$.asObservable()
  }

  public setInvestments(investPortifolio){
    this.investments$.next(investPortifolio)
  }
}

但是在我的 html 中没有出现来自 api 的数据。

menu.component.ts

export class MenuComponent implements OnInit {
  
  investments$: Observable<any>;

  constructor( private coreService : CoreService ) {
    this.investments$ = this.coreService.getInvestments$()
   }


  ngOnInit(): void {
    this.coreService.loadInvestments();
    console.log(this.coreService.loadInvestments())
  }

}

menu.component.html

    <div>
        test
    </div>

    <div *ngFor="let investimentPortifolio of investments$ | async;">
        {{investimentPortifolio | json}}
    </div>

【问题讨论】:

  • 这是一个时间问题。看看stackoverflow.com/questions/14220321/…
  • 无论如何我建议不要在服务中存储固定属性,而是将值提供为可观察的以及哪些组件可以订阅(可能使用async pipe)。搜索 behaviorsubject 和 asobservable。
  • 我研究了你说的,你知道为什么数据没有出现在屏幕上吗?
  • 你需要在 this.coreService.loadInvestMents() 上调用 subscribe

标签: javascript angular typescript rxjs architecture


【解决方案1】:

listInvestments 方法正在执行异步 API 调用。因此,当您在其上调用 forEach 时,基本上投资属性仍然未定义。

您希望在从服务器加载数据之后而不是之前循环投资数组。

一种方法是确保您在订阅的 next() 回调中,并且您确定您拥有执行操作所需的数据。

CoreService 类变为:

@Injectable({
    providedIn: 'root'
})
export class CoreService {
    public investments: any;
    constructor(private api: ConsolidadoApi, private state: StateService) {}

    public createMenu(){
      this.api.getInvestments()
            .subscribe(response => {
                this.investments = response;
                this.investments.forEach(element => {
                  console.log(element)
                });
            })
       
    }
}

问题编辑更新

在 ngOnInit 中,您调用了 loadInvestments(),它返回了一个 observable。并且 observable 是惰性的,这意味着如果你没有对它们调用 subscribe 什么都不会发生。

你需要做的是改变这一行:

this.coreService.loadInvestments();

this.coreService.loadInvestments().subscribe();

【讨论】:

  • 首先感谢您的回答。但是当我在未定义的组件中调用 createMenu() 时,我已经尝试过这种方式,您知道如何解决它吗?
  • 原始问题已被编辑,因此我将更新我的答案。
  • 很有趣,但我怎样才能将数据放入 html 中?
  • @GuilhermeLucas 通常,使用async pipe 将在幕后为您提供可在 html 模板中使用的 observable 的“值”(管道执行订阅并为您提供用作模板变量)。现在,从外观上看,您只是存储了普通的 json 响应并尝试显示它。如果这意味着要单独访问其属性的对象,则需要将 json 反序列化为 javascript 对象。如果您对此不熟悉,请查看角度教程 (6.):angular.io/tutorial
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
  • 2020-06-11
  • 2019-10-18
  • 2016-05-17
相关资源
最近更新 更多