从 angular2 服务中使用 web 服务的问题

Issue in consuming webservice from angular2 service

我试图创建一个服务,该服务将从 .json 文件中读取数据并呈现一个包含 json 数据的方法,该方法将由 angular2 组件调用。 (理想情况下,在实时应用程序中,服务将使用 WebAPI 服务和 return angular2 组件的数据) 从服务读取的 JSon 数据将以 BubbleChart 的形式呈现,由 bubblechartcomponent 负责处理。我能够在不使用服务的情况下渲染气泡图,但在引入 angular2 服务组件后它停止工作了。谁能帮我确定问题并解决这个问题?

请找模拟实际应用的plunker https://plnkr.co/edit/9RjP4rpY4d7EnA4Z5sRQ?p=preview

数据服务的代码如下

    import { Injectable } from 'angular2/core';
import { HTTP_PROVIDERS, Http, Headers, Response, JSONP_PROVIDERS, Jsonp } from 'angular2/http';
import { Configuration } from './Configuration';
import 'rxjs/add/operator/map'
import { Observable } from 'rxjs/Observable';

///Service class to call REST API
@Injectable()
export class DataService {

    private DataServerActionUrl: string;
    private headers: Headers;
    result: Object;

    constructor(private _http: Http) {
        console.log("constructor of DataService with Http Injectable");
        //this.DataServerActionUrl = "http://localhost:23647/api/extractorqueue/getextractorqueueslatest/"; 
        this.DataServerActionUrl = "Bubblechartdata.json":
    }

    public GetExtractorQueuesLatest = (): Observable<Response> => {
        console.log("Inside method GetExtractorQueuesLatest");
        console.log("API URL: " + this.DataServerActionUrl);

         return this._http.get(this.DataServerActionUrl)
            .map(Response => Response.json())
            .catch(this.handleError);
    }

    private handleError(error: any) {
        console.log("in Error");
        let errMsg = (error.message) ? error.message :
            error.status ? `${error.status} - ${error.statusText}` : 'Server error';
        console.error(errMsg); // log to console instead
        return Observable.throw(errMsg);
    }
}

我的 Main.ts 文件如下所示

//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS, Http, Headers, Response, JSONP_PROVIDERS, Jsonp } from 'angular2/http';
import {DataService} from './DataService';
import {BubbleChartComponent} from './BubbleChartComponent';

bootstrap(BubbleChartComponent, [DataService, HTTP_PROVIDERS])
  .catch(err => console.error(err));

我的气泡图组件如下所示

import { HTTP_PROVIDERS, Http, Headers, Response, JSONP_PROVIDERS, Jsonp } from 'angular2/http';
import { Component, OnInit } from 'angular2/core';
import { CORE_DIRECTIVES } from 'angular2/common';
import { DataService } from '../DataService';
declare var d3: any;

@Component({
    styles: [``],
    directives: [CORE_DIRECTIVES],
    providers: [DataService, HTTP_PROVIDERS],
    templateUrl: 'bubblechart.html'
})

export class BubbleChartComponent implements OnInit {
    public resultData: any;

    constructor(private _dataService: DataService) { }

    ngOnInit() {
        this._dataService.GetExtractorQueuesLatest()
            .subscribe(
            (res) => {
                this.resultData = res;
                this.DrawBubbleChart();
            },
            (error) => console.log(error),
            () => console.log('Extractor Queues Latest')
            );
    }

    margin = 25;
    diameter = 915;
    color = d3.scale.linear()
        .domain([-1, 5])
        .range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
        .interpolate(d3.interpolateHcl);

    pack = d3.layout.pack()
        .padding(2)
        .size([this.diameter - this.margin, this.diameter - this.margin])
        .value(function (d) { return d.size; })

    svg = d3.select("router-outlet").append("svg")
        .attr("width", this.diameter)
        .attr("height", this.diameter)
        .append("g")
        .attr("transform", "translate(" + this.diameter / 2 + "," + this.diameter / 2 + ")");

    private DrawBubbleChart(): void {

        var chart = d3.json(this.resultData, (error, root) => {
            if (error) throw error;

            var focus = root,
                nodes = this.pack.nodes(root),
                view;

            var circle = this.svg.selectAll("circle")
                .data(nodes)
                .enter().append("circle")
                .attr("class", function (d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
                .style("fill", (d) => { return d.children ? this.color(d.depth) : null; })
                .on("click", (d) => { if (focus !== d) zoom.call(this, d), d3.event.stopPropagation(); });

            var text = this.svg.selectAll("text")
                .data(nodes)
                .enter().append("text")
                .attr("class", "label")
                .style("fill-opacity", function (d) { return d.parent === root ? 1 : 0; })
                .style("display", function (d) { return d.parent === root ? "inline" : "none"; })
                .text(function (d) { return d.name; });

            var node = this.svg.selectAll("circle,text");

            d3.select("router-outlet")
                .style("background", this.color(-1))
                .on("click", () => { zoom.call(this, root); });

            zoomTo.call(this, [root.x, root.y, root.r * 2 + this.margin]);

            function zoom(d) {
                var focus0 = focus; focus = d;

                var transition = d3.transition()
                    .duration(d3.event.altKey ? 7500 : 750)
                    .tween("zoom", (d) => {
                        var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + this.margin]);
                        return (t) => { zoomTo.call(this, i(t)); };
                    });

                transition.selectAll("text")
                    .filter(function (d) { return d.parent === focus || this.style.display === "inline"; })
                    .style("fill-opacity", function (d) { return d.parent === focus ? 1 : 0; })
                    .each("start", function (d) { if (d.parent === focus) this.style.display = "inline"; })
                    .each("end", function (d) { if (d.parent !== focus) this.style.display = "none"; });
            }

            function zoomTo(v) {
                var k = this.diameter / v[2]; view = v;
                node.attr("transform", function (d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
                circle.attr("r", function (d) { return d.r * k; });
            }
        });
    }

}

Index.html 文件中添加了以下引用

<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.26/system-polyfills.js"></script>
<script src="https://npmcdn.com/angular2@2.0.0-beta.16/es6/dev/src/testing/shims_for_IE.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.16/angular2-polyfills.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.26/system.js"></script>
<script src="https://npmcdn.com/typescript@1.8.10/lib/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.16/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.16/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>

不确定如何在 plunker 中添加以下行,但在我的代码的本地版本中,我已将其包含在我的 Index.html 文件中

<script src="node_modules/angular2/bundles/http.dev.js"></script>

我还缺少什么让它发挥作用?请帮助

您需要更正几个错误

index.html

您在 ln#23 上错误地导入了 bootstrap 而不是 main 它应该是 app

System.import('app')

src/DataService.ts

您缺少 rxjs catch 运算符的导入 import 'rxjs/add/operator/catch';

src/BubbleChartComponent.ts

你导入数据服务的路径是正确的,应该是 import { DataService } from './DataService';

应用问题

修复这些问题后,您将看到对 https://run.plnkr.co/LOM2gOWjWHv4fTSE/[object%20Object] 的 404 请求。检查堆栈显示它来自 BubbleChartComponent.DrawBubbleChart。

我对 d3 不是很熟悉,但我猜你是导入数据的错误函数。您正在使用 var chart = d3.json(this.resultData, (error, root) => { 在 ln#52 上,从一个快速的 google 这需要一个到 json 文件的路径,但是 this.resultData 是一个对象。