我正在开发一个Angular 2项目,我有一项名为“MockService'使用名为' getMockData()'的方法在我的组件中使用如下:
import { Component, OnInit } from '@angular/core';
import { Mock } from './mock';
//import { MOCK } from './mock-data';
import { MockService } from '../mock.service';
import { Chart } from 'chart.js';
import 'chart.piecelabel.js';
@Component({
selector: 'app-viz',
templateUrl: './viz.component.html',
styleUrls: ['./viz.component.scss']
})
export class VizComponent implements OnInit {
mock:Mock;
options = {
responsive: true,
tooltips: {
enabled: false
},
legend: {
display: false
},
pieceLabel:{
render: 'percetage',
precision: 0,
// identifies whether or not labels of value 0 are displayed, default is false
showZero: true,
// font size, default is defaultFontSize
fontSize: 12,
// font color, can be color array for each data or function for dynamic color, default is defaultFontColor
fontColor: ['green', 'blue'],
// font style, default is defaultFontStyle
fontStyle: 'normal',
// font family, default is defaultFontFamily
fontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// draw text shadows under labels, default is false
textShadow: true,
// text shadow intensity, default is 6
shadowBlur: 10,
// text shadow X offset, default is 3
shadowOffsetX: -5,
// text shadow Y offset, default is 3
shadowOffsetY: 5,
// text shadow color, default is 'rgba(0,0,0,0.3)'
shadowColor: 'rgba(255,0,0,0.75)',
// draw label in arc, default is false
arc: false,
// position to draw label, available value is 'default', 'border' and 'outside'
// default is 'default'
position: 'outside'
}
}
constructor(private mockService: MockService) {
}
ngOnInit() {
this.getData();
let ctx = "myChart";
let myChart = new Chart(ctx,{
type: this.mock.type,
data: this.mock.data,
options: this.options
})
}
getData(): void {
this.mockService.getMockData()
.subscribe(mock_data => {
this.mock = mock_data;
});
}
}
和' MockService'如下:
import { Injectable } from '@angular/core';
import { Mock } from './viz/mock';
import { MOCK } from './viz/mock-data';
import { Observable} from 'rxjs';
import { of } from 'rxjs/observable/of';
import { HttpClient, HttpHeaders } from '@angular/common/http';
@Injectable()
export class MockService {
private mockUrl = 'api/MOCK';
constructor(
private http: HttpClient
) { }
getMockData(): Observable<Mock> {
//return of(MOCK);
return this.http.get<Mock>(this.mockUrl);
}
}
问题是当我使用&#39;&#39;操作员返回数据,代码没有中断,图表按预期显示。但是,当我使用&#39; http.get&#39;方法,&#39;模拟&#39;我的组件中的属性变得不确定。它在subscribe方法中定义。我可以使用控制台来记录它。但是在方法之外的任何地方,即使在&#39; getData()&#39;方法,它是未定义的。我怎样才能使用&#39; http.get&#39;方法实现与以前相同的功能?
答案 0 :(得分:0)
你的问题是http.get
是asyncronus
尝试这样的事情:
getData(): Promise<Mock> {
return new Promise(r => {
this.mockService.getMockData()
.subscribe(mock_data => {
r(mock_data);
});
});
}
然后在ngOnInit
ngOnInit() {
this.getData().then((mock) => {
this.mock = mock;
let ctx = "myChart";
let myChart = new Chart(ctx,{
type: this.mock.type,
data: this.mock.data,
options: this.options
})
});
}
如果你希望你的代码更具可读性,你也可以使用像这样的async / await语法:
ngOnInit() {
(async () => {
this.mock = await this.getData();
...
})();
}
注意角度你不应该使用循环函数(如OnInit)async,如:
// NOT LIKE THIS
async ngOnInit() { ... }
// or
ngOnInit = async function() { ... }
答案 1 :(得分:0)
尝试:
ngOnInit() {
let ctx = "myChart";
this.mockService.getMockData()
.subscribe(mock_data => {
this.mock = mock_data;
let myChart = new Chart(ctx,{
type: mock_data.type,
data: mock_data.data,
options: this.options
})
});
}
答案 2 :(得分:0)
如果在订阅完成之前尝试使用this.mock
,则将不确定。
因为当您使用http请求加载数据时,在执行订阅代码之前会有一段延迟。
所以我的建议是创建一个从订阅中调用的refresh()方法,该方法更新依赖于this.mock
的其他对象。
这样的事情可能是:
getData(): void {
this.mockService.getMockData()
.subscribe(mock_data => {
this.mock = mock_data;
this.refresh();
});
}
refresh() {
let myChart = new Chart(ctx,{
type: this.mock.type,
data: this.mock.data,
options: this.options
})
}
答案 3 :(得分:0)
observable是异步的,因此在初始化Chart
时它没有完成。您可以通过将其转换为promise并使用async / await
async ngOnInit() {
this.mock = await this.getData();
...
}
getData()方法:
getData(): Promise<Mock> {
return this.mockService.getMockData().toPromise();
}