加载本地 json 与 Angular 中的 httpclient 服务异步
Load local json async with httpclient service in Angular
我正在尝试使用 Angular 服务调用负载 Json,而不是在 ngOnInit 上,而是在用户请求的按钮上。它接缝它确实加载它但不执行它异步。我收到此错误:错误错误:未捕获(承诺):类型错误:
我是 Angular 的新手,所以请不要评判。
core.js:15724 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
at PollComponent.push../src/app/components/poll/poll.component.ts.PollComponent.shuffle (poll.component.ts:23)
at PollComponent.<anonymous> (poll.component.ts:44)
at step (tslib.es6.js:97)
at Object.next (tslib.es6.js:78)
at fulfilled (tslib.es6.js:68)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
at Object.onInvoke (core.js:17299)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:150)
at zone.js:889
at resolvePromise (zone.js:831)
at zone.js:741
at fulfilled (tslib.es6.js:68)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
at Object.onInvoke (core.js:17299)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:150)
at zone.js:889
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17290)
defaultErrorLogger @ core.js:15724
push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError @ core.js:15772
next @ core.js:17771
schedulerFn @ core.js:13515
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:196
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:134
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:77
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54
push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47
push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit @ core.js:13499
(anonymous) @ core.js:17321
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:391
push../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:150
push../node_modules/@angular/core/fesm5/core.js.NgZone.runOutsideAngular @ core.js:17258
onHandleError @ core.js:17321
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.handleError @ zone.js:395
push../node_modules/zone.js/dist/zone.js.Zone.runGuarded @ zone.js:164
_loop_1 @ zone.js:694
api.microtaskDrainDone @ zone.js:703
drainMicroTaskQueue @ zone.js:608
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:502
invokeTask @ zone.js:1744
globalZoneAwareCallback @ zone.js:1770
这是我的服务:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { IQuestion } from '../../assets/IData';
@Injectable({
providedIn: 'root'
})
export class PollServiceService {
private _url: string = "assets/data/TEST_me_50_Pyetje.json";
constructor(private http: HttpClient) {
}
getQuestions() : Observable<IQuestion[]> {
return this.http.get<IQuestion[]>(this._url);
}
}
这是我的方法。它在 HTML:
中的按钮上调用
ngOnInit() {
}
async startTestClick(){
var promise = await this.pollService.getQuestions().subscribe(data => this.que = data);
this.nrSakte = 0;
this.testQuestions = this.shuffle(this.que).slice(0,50);
for (let entry of this.testQuestions) {
entry.picture ="A";
entry.color = "black";
}
let a = await document.getElementsByClassName("alternativa");
for(let j in a){
a[j].setAttribute("style", "background-color:#fafafa;");
}
}
我真的希望它等到整个 Json 加载完毕,以便我可以选择要在 HTML 上显示的元素。它确实显示了它们,但它显示了这个错误。如果我想动态加载其他一些 json 它不再起作用。
提前致谢!
我认为您需要在调用 startTestClick
时在 subscribe
中移动一些逻辑。
像这样:
async startTestClick() {
var promise = await this.pollService.getQuestions().subscribe(data => {
this.que = data;
this.nrSakte = 0;
this.testQuestions = this.shuffle(this.que).slice(0,50);
for (let entry of this.testQuestions) {
entry.picture ="A";
entry.color = "black";
}
});
...
}
如果没有这个,您的其余代码将进入 运行,而 subscribe
正在等待结果,而 this.que
还没有任何结果。
我不认为你真的需要 async/await
。所以,这也可以。
startTestClick() {
this.pollService.getQuestions().subscribe(data => {
this.que = data;
this.nrSakte = 0;
this.testQuestions = this.shuffle(this.que).slice(0,50);
for (let entry of this.testQuestions) {
entry.picture ="A";
entry.color = "black";
}
});
...
}
再一次,您在 document.getElementsByClassName
调用中使用了 await
,所以我可能是错的。该调用可能也需要在 subscribe
内。
两种方法都试一下,看看哪个有效。如果这不能解决您的问题,我可以删除此答案。这是根据 post 中的内容做出的一些猜测,但是 方式 太多了,无法发表评论。
我正在尝试使用 Angular 服务调用负载 Json,而不是在 ngOnInit 上,而是在用户请求的按钮上。它接缝它确实加载它但不执行它异步。我收到此错误:错误错误:未捕获(承诺):类型错误:
我是 Angular 的新手,所以请不要评判。
core.js:15724 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
at PollComponent.push../src/app/components/poll/poll.component.ts.PollComponent.shuffle (poll.component.ts:23)
at PollComponent.<anonymous> (poll.component.ts:44)
at step (tslib.es6.js:97)
at Object.next (tslib.es6.js:78)
at fulfilled (tslib.es6.js:68)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
at Object.onInvoke (core.js:17299)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:150)
at zone.js:889
at resolvePromise (zone.js:831)
at zone.js:741
at fulfilled (tslib.es6.js:68)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
at Object.onInvoke (core.js:17299)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:150)
at zone.js:889
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17290)
defaultErrorLogger @ core.js:15724
push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError @ core.js:15772
next @ core.js:17771
schedulerFn @ core.js:13515
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:196
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:134
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:77
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54
push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47
push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit @ core.js:13499
(anonymous) @ core.js:17321
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:391
push../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:150
push../node_modules/@angular/core/fesm5/core.js.NgZone.runOutsideAngular @ core.js:17258
onHandleError @ core.js:17321
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.handleError @ zone.js:395
push../node_modules/zone.js/dist/zone.js.Zone.runGuarded @ zone.js:164
_loop_1 @ zone.js:694
api.microtaskDrainDone @ zone.js:703
drainMicroTaskQueue @ zone.js:608
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:502
invokeTask @ zone.js:1744
globalZoneAwareCallback @ zone.js:1770
这是我的服务:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { IQuestion } from '../../assets/IData';
@Injectable({
providedIn: 'root'
})
export class PollServiceService {
private _url: string = "assets/data/TEST_me_50_Pyetje.json";
constructor(private http: HttpClient) {
}
getQuestions() : Observable<IQuestion[]> {
return this.http.get<IQuestion[]>(this._url);
}
}
这是我的方法。它在 HTML:
中的按钮上调用 ngOnInit() {
}
async startTestClick(){
var promise = await this.pollService.getQuestions().subscribe(data => this.que = data);
this.nrSakte = 0;
this.testQuestions = this.shuffle(this.que).slice(0,50);
for (let entry of this.testQuestions) {
entry.picture ="A";
entry.color = "black";
}
let a = await document.getElementsByClassName("alternativa");
for(let j in a){
a[j].setAttribute("style", "background-color:#fafafa;");
}
}
我真的希望它等到整个 Json 加载完毕,以便我可以选择要在 HTML 上显示的元素。它确实显示了它们,但它显示了这个错误。如果我想动态加载其他一些 json 它不再起作用。
提前致谢!
我认为您需要在调用 startTestClick
时在 subscribe
中移动一些逻辑。
像这样:
async startTestClick() {
var promise = await this.pollService.getQuestions().subscribe(data => {
this.que = data;
this.nrSakte = 0;
this.testQuestions = this.shuffle(this.que).slice(0,50);
for (let entry of this.testQuestions) {
entry.picture ="A";
entry.color = "black";
}
});
...
}
如果没有这个,您的其余代码将进入 运行,而 subscribe
正在等待结果,而 this.que
还没有任何结果。
我不认为你真的需要 async/await
。所以,这也可以。
startTestClick() {
this.pollService.getQuestions().subscribe(data => {
this.que = data;
this.nrSakte = 0;
this.testQuestions = this.shuffle(this.que).slice(0,50);
for (let entry of this.testQuestions) {
entry.picture ="A";
entry.color = "black";
}
});
...
}
再一次,您在 document.getElementsByClassName
调用中使用了 await
,所以我可能是错的。该调用可能也需要在 subscribe
内。
两种方法都试一下,看看哪个有效。如果这不能解决您的问题,我可以删除此答案。这是根据 post 中的内容做出的一些猜测,但是 方式 太多了,无法发表评论。