这很奇怪.它也有点长,所以提前道歉. 更新 - 它最终成为2个问题,请参阅下面的答案.
这是我的错误: EXCEPTION: this.svg.selectAll(...).data(...).enter is not a function
我有一个angular-cli客户端和一个节点api服务器.我可以使用observable从服务中检索states.json文件(下面的代码).d3喜欢该文件并显示预期的美国地图.
当我将api服务器中的服务目标从文件更改为bluemix-cloudant服务器时,我在客户端收到上述错误.
当我使用ngOnInit在一个变体中使用console.log输出时,最初mapData打印为一个空数组,并抛出错误.这是错误的明显来源,因为没有数据,但Chrome调试器显示待处理的请求.请求完成后,数据将按预期在控制台中打印.
angular-cli版本1.0.0-beta.26
角度版本^ 2.3.1
d3版本^ 4.4.4
rxjs版本^ 5.0.1
map.component.ts:
import { Component, ElementRef, Input } from '@angular/core'; import * as D3 from 'd3'; import '../rxjs-operators'; import { MapService } from '../map.service'; @Component({ selector: 'map-component', templateUrl: './map.component.html', styleUrls: ['./map.component.css'] }) export class MapComponent { errorMessage: string; height; host; htmlElement: HTMLElement; mapData; margin; projection; path; svg; width; constructor (private _element: ElementRef, private _mapService: MapService) { this.host = D3.select(this._element.nativeElement); this.getMapData(); this.setup(); this.buildSVG(); } getMapData() { this._mapService.getMapData() .subscribe( mapData => this.setMap(mapData), error => this.errorMessage =error ) } setup() { this.margin = { top: 15, right: 50, bottom: 40, left: 50 }; this.width = document.querySelector('#map').clientWidth - this.margin.left - this.margin.right; this.height = this.width * 0.6 - this.margin.bottom - this.margin.top; } buildSVG() { this.host.html(''); this.svg = this.host.append('svg') .attr('width', this.width + this.margin.left + this.margin.right) .attr('height', this.height + this.margin.top + this.margin.bottom) .append('g') .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')'); } setMap(mapData) { this.mapData = mapData; this.projection = D3.geoAlbersUsa() .translate([this.width /2 , this.height /2 ]) .scale(650); this.path = D3.geoPath() .projection(this.projection); this.svg.selectAll('path') .data(this.mapData.features) .enter().append('path') .attr('d', this.path) .style('stroke', '#fff') .style('stroke-width', '1') .style('fill', 'lightgrey'); } }
map.service.ts:
import { Http, Response } from '@angular/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; @Injectable() export class MapService { private url = 'http://localhost:3000/api/mapData'; private socket; constructor (private _http: Http) { } getMapData(): Observable{ return this._http.get(this.url) .map(this.extractData) .catch(this.handleError); } private extractData(res: Response) { let body = res.json(); return body.data || {}; } private handleError(error: any) { let errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error'; console.error(errMsg); return Promise.reject(errMsg); } }
这是异步的功能,对数据的调用对于d3来说需要太长时间吗?
我曾希望这个问题 Uncaught TypeError:canvas.selectAll(...).data(...).enter不是d3中的一个函数会提供一些见解,但我没有看到任何.
非常感谢任何帮助或见解!
编辑: 以下是Chrome per Marks请求下方标题部分的屏幕截图.响应选项卡显示正确作为GeoJSON对象发送的数据.我还将该响应复制到本地文件中,并将其用作具有正面结果的地图源.
到目前为止的数据测试:GeoJSON文件(2.1mb)
本地文件,本地服务器:成功(响应时间54ms)
相同文件,远程服务器:数据返回浏览器前D3错误(750ms)
来自远程服务器的API调用:数据返回浏览器之前的D3错误(2.1 s)