使用httpclient的可观察对象的问题

时间:2018-11-06 10:08:34

标签: angular d3.js observable

我正在尝试转换示例component 使用可观察对象通过HTTP传输STOCKS数组。

我已将lineChartComponent中的代码修改为:

import { Component, ViewEncapsulation, OnInit } from '@angular/core';

import * as d3 from 'd3-selection';
import * as d3Scale from 'd3-scale';
import * as d3Shape from 'd3-shape';
import * as d3Array from 'd3-array';
import * as d3Axis from 'd3-axis';

import { STOCKS } from '../shared';
import { Stock } from '../stock';

import { GraphService } from '../graph.service';

@Component({
    selector: 'app-line-chart',
    encapsulation: ViewEncapsulation.None,
    templateUrl: './line-chart.component.html',
    styleUrls: ['./line-chart.component.css']
})
export class LineChartComponent implements OnInit {

    title = 'Line Chart';

    stocks: Stock[];

    private margin = { top: 20, right: 20, bottom: 30, left: 50 };
    private width: number;
    private height: number;
    private x: any;
    private y: any;
    private svg: any;
    private line: d3Shape.Line<[number, number]>;

    constructor(private graphService: GraphService) {

        this.width = 900 - this.margin.left - this.margin.right;
        this.height = 500 - this.margin.top - this.margin.bottom;

    }

    ngOnInit() {
        this.getStocks();

        this.initSvg();
        this.initAxis();
        this.drawAxis();
        this.drawLine();
    }

    getStocks(): void {
        this.graphService.getStocks()
        .subscribe(stocks => this.stocks = stocks);
      }

    private initSvg() {
        this.svg = d3.select('svg')
            .append('g')
            .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
    }

    private initAxis() {
        this.x = d3Scale.scaleTime().range([0, this.width]);
        this.y = d3Scale.scaleLinear().range([this.height, 0]);
        this.x.domain(d3Array.extent(this.stocks, (d) => d.date));
        this.y.domain(d3Array.extent(this.stocks, (d) => d.value));
    }

    private drawAxis() {

        this.svg.append('g')
            .attr('class', 'axis axis--x')
            .attr('transform', 'translate(0,' + this.height + ')')
            .call(d3Axis.axisBottom(this.x));

        this.svg.append('g')
            .attr('class', 'axis axis--y')
            .call(d3Axis.axisLeft(this.y))
            .append('text')
            .attr('class', 'axis-title')
            .attr('transform', 'rotate(-90)')
            .attr('y', 6)
            .attr('dy', '.71em')
            .style('text-anchor', 'end')
            .text('Price ($)');
    }

    private drawLine() {
        this.line = d3Shape.line()
            .x((d: any) => this.x(d.date))
            .y((d: any) => this.y(d.value));

        this.svg.append('path')
            .datum(this.stocks)
            .attr('class', 'line')
            .attr('d', this.line);
    }

}

graphService在哪里

import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';

import { LineChartComponent } from './graph/line-chart.component';
//import { STOCKS } from './shared';
import { Stock } from './stock';
import { MessageService } from './message.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';

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

  private stocksUrl = 'api/stocks';

  constructor(
    private http: HttpClient,
    private messageService: MessageService) { }

  getStocks(): Observable<Stock[]> {
    // TODO: send the message _after_ fetching the heroes
    this.messageService.add('GraphService: fetched graph data');
    return this.http.get<Stock[]>(this.stocksUrl);
    //return of(STOCKS);
  }

}

并且stock

export class Stock {
  date: Date;
  value: number;
}

我正在使用ImMemoryDBService模拟HTTP服务器端

import { InMemoryDbService } from 'angular-in-memory-web-api';
//import { Stock } from './stock';

export class InMemoryDataService implements InMemoryDbService {
  createDb() {
      const stocks = [
        {date: new Date('2010-01-01'), value: 210.73},
        {date: new Date('2010-01-04'), value: 214.01},
        {date: new Date('2010-01-05'), value: 214.38},
        {date: new Date('2010-01-06'), value: 210.97},
.....

如果我将GraphService更改为

return of(STOCKS)

它工作正常,图形绘制正确。

似乎在

失败
this.x.domain(d3Array.extent(this.stocks, (d) => d.date));

with TypeError:无法读取未定义的属性“ length”

我想知道是否是因为IMPORTS中的数据被定义为常量。

1 个答案:

答案 0 :(得分:0)

这个问题有两个方面。首先,图形需要等待可观察到的返回数据。其次,通过http返回的日期数据将作为字符串返回,并且需要转换为日期格式:

getStocks(): void {
    this.graphService.getStocks()
    .subscribe(stocks => {
        this.stocks = stocks
        for (let i in stocks) stocks[i].date = new Date(stocks[i].date);
        console.log(stocks);
        this.initAxis();
        this.drawAxis();
        this.drawLine();
  });