观测值如何工作?

时间:2018-07-08 03:02:40

标签: angular

我已经与angularjs合作了一段时间,并且开始使用Angular(angular.io),但是我在理解Observables时遇到了麻烦(这是我的第一个应用程序。)

我有一个HTTP响应,需要将其由D3.js转换为D3.hierarchy,然后在of(Rentabilidade.service.ts)中使用getResumo$()返回一个空的Observable

此空的Observable将在组件(resumo.component.ts)中进行订阅。

在服务中,因为我需要转换数据,所以我订阅了Observable来操纵数据并更新此空的Observable。

但是组件中的console.log(d)从未更新。仅在我的控制台中打印undefined

我在做什么错了?

P.S:如果我在服务中插入console.log(this.hierarchy$),则数据已更新,但没有传播到组件。

Rentabilidade.service.ts

import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http'
import { Observable, Observer, of, from} from 'rxjs';
import { catchError, map, tap, filter } from 'rxjs/operators';
import * as d3 from "d3";

@Injectable({
  providedIn: 'root'
})
export class RentabilidadeService {
    private f_rntb_agg_rsmo = 'http://localhost/api/index.php/bco_dav_dm/f_rntb_agg_rsmo';
    private hierarchy$: Observable<any>;

  constructor(private http: HttpClient) { 
  }

  getResumo$(): Observable<any> {

    this.http.get(this.f_rntb_agg_rsmo)
    .pipe(
      catchError(this.handleError('getResumo',[]))
    )
    .subscribe(d => {

    let nest = d3.nest()
      .key(k => 'root')
      .key(k => k.servico)
      .key(k => k.produto_comercial)
      .key(k => k.canal)
      .key(k => k.ddd)
      .key(k => k.nome_rede)
      .entries(d);

    let hierarchy =  d3.hierarchy(nest[0], h => h.values)
    
    hierarchy.eachAfter(x=> {x.contribuicao = x.sum(y=>y.contribuicao_mes_atul).value;
                  x.contribuicao_mom = x.sum(y=>y.contribuicao_mes_atul - y.contribuicao_mes_antr).value;
                  x.contribuicao_yoy = x.sum(y=>y.contribuicao_mes_atul - y.contribuicao_ano_antr).value;
    });

    this.hierarchy$ = hierarchy;
  }
  )
  return Observable.create(observer => observer.next(this.hierarchy$));

  }
  
  private handleError(operation = 'nao informado', result?: any) {
    return (error: any): Observable<any> => {
      console.error(error);
      return of(result);
    }
  }
}

resumo.component.ts

import { Component, OnInit } from '@angular/core';
import { RentabilidadeService } from '../rentabilidade.service';

@Component({
  selector: 'rentabilidade-resumo',
  templateUrl: './resumo.component.html',
  styleUrls: ['./resumo.component.css']
})
export class ResumoComponent implements OnInit {
  
  resumo = [];

  constructor(private rentabilidadeService: RentabilidadeService) {}

  ngOnInit() {
    this.rentabilidadeService.getResumo$()
    .subscribe(d => {this.resumo = d; console.log(d)});
  }
 
}

1 个答案:

答案 0 :(得分:0)

在您的getResumo$方法http.get()上是一个异步调用,函数的返回调用将等到它从服务器获得响应后再等待。

如果您要处理来自http请求的数据,可以尝试此方法。

返回http请求方法,然后在组件上编写数据嵌套函数。如果选择此方法,则如果您有多个依赖于此类型数据操作的组件,则可能必须在应用程序的多个位置编写相同的方法(除非使用服务)。 示例:

    getResumo$(): Observable<any> {
       retun this.http.get(this.f_rntb_agg_rsmo);
    }

然后在您的component.ts文件上订阅响应。

或者您可以将整个getResumo$()包装在Observable.create中 例如:

getResumo$(): Observable<any> {
  return Observable.create(observer => {
    this.http.get(this.f_rntb_agg_rsmo)
        .pipe(catchError(this.handleError('getResumo',[])))
        .subscribe(d => {
      let nest = d3.nest()
      .key(k => 'root')
      .key(k => k.servico)
      .key(k => k.produto_comercial)
      .key(k => k.canal)
      .key(k => k.ddd)
      .key(k => k.nome_rede)
      .entries(d);

      let hierarchy =  d3.hierarchy(nest[0], h => h.values)

      hierarchy.eachAfter(x=> {x.contribuicao = 
        x.sum(y=>y.contribuicao_mes_atul).value;
        x.contribuicao_mom = x.sum(y=>y.contribuicao_mes_atul - 
        y.contribuicao_mes_antr).value;
        x.contribuicao_yoy = x.sum(y=>y.contribuicao_mes_atul - 
        y.contribuicao_ano_antr).value;
      });
      this.hierarchy$ = hierarchy;
      observer.next(this.hierarchy$));
    });
    }
  }