【问题标题】:Load local json async with httpclient service in Angular在Angular中使用httpclient服务加载本地json异步
【发布时间】:2019-05-18 19:46:09
【问题描述】:

我正在尝试使用 Angular 服务调用 load Json,而不是在 ngOnInit 上,而是在用户请求的 Button 上。它接缝确实会加载它,但不会异步执行。我收到此错误:错误错误:未捕获(承诺中):类型错误:

我是 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,它就不再起作用了。

提前致谢!

【问题讨论】:

  • 感谢您的回复。这是不一样的。它确实会加载数据,但不会异步执行。我认为 .subscribe() 是异步的。我只是尝试执行第 1 步和第 2 步,但仍然没有改变行为。 @jpavel
  • 关于尝试重新排列代码,例如,将getQuestions() 的返回类型切换为承诺return this.http.get&lt;IQuestion[]&gt;(this._url).toPromise(); => 我注意到你想稍后使用await...
  • 请检查 PollComponent 中的 shuffle 功能。你的帖子中没有给出。
  • 我试图使用等待,如果可以观察到的话,我真的不需要它。我只想完全加载 Json(文件大小 11MB),然后才执行 thisthis.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 = document.getElementsByClassName("alternativa"); for(let j in a){ a[j].setAttribute("style", "background-color:#fafafa;"); } @jpavel

标签: json angular asynchronous httpclient angular-services


【解决方案1】:

我认为您需要在对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 内。

尝试两种方法,看看哪种方法有效。如果这不能解决您的问题,我可以删除此答案。根据帖子中的内容,这有点猜测,但方式太多了,无法发表评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-31
    • 2016-04-08
    • 2015-05-26
    • 2015-12-15
    • 2018-05-25
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多