1

I'm trying to call load Json with Angular service not on ngOnInit but on a Button on user request. It seams it does load it but does not do it async. I get this error: ERROR Error: Uncaught (in promise): TypeError:

I'm new to Angular so pls don't judge.

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

Here is my Service :

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);
   }
}

and here is my method. It is called on a button in 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;");
      }
  }

I really want it to wait until the whole Json is loaded so that I can chose which elements to show on HTML. It does show them but it shows this errors. If I want to load dynamically some other json it does not work any more.

Thanks in advance!

8
  • Take a look at this answer: stackoverflow.com/a/47023181/6433166 Commented May 18, 2019 at 20:07
  • I did thanks for the reply. It is not the same. It does load the data but it does not do it async. I thought .subscribe() does it async. I just tried to do step 1 and 2 still no change of behaviour. @jpavel Commented May 18, 2019 at 20:17
  • And about trying to rearrange your code, for example, switching the return type of getQuestions() to a promise return this.http.get<IQuestion[]>(this._url).toPromise(); => I've noticed you want to use await later... Commented May 18, 2019 at 20:30
  • Please check the shuffle function in PollComponent. That was not given in your post. Commented May 18, 2019 at 20:34
  • I was trying to use await i really don't need it if it is possible with observable. I just want to fully load the Json( file size 11MB ) and only after to execute 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 Commented May 18, 2019 at 20:34

1 Answer 1

-1

I think you need to move some logic inside the subscribe in your call to startTestClick.

Something like this:

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";
        }
    });
    ...
}

Without this, the rest of your code is going to run while the subscribe is waiting for results, and this.que doesn't have anything yet.

I don't think you really need the async/await. So, this could work, too.

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";
        }
    });
    ...
}

Then again, you're using an await on the document.getElementsByClassName call, so I could be wrong. That call may need to be inside the subscribe, too.

Try it both ways, see which works. If this doesn't solve your issue, I can delete this answer. This is a bit of a guess based on what's in the post, but way too much to put in a comment.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.