Riscie
Riscie

Reputation: 4629

Angular2 App breaks when trying to load mocked data with a Promise

I am trying to load my mocked data with a promise like the Angular2 Tutorial does it here.

Service (Mock):

import { Injectable } from '@angular/core';
import { ERGEBNISSE } from "./mock-ergebnisse";

@Injectable()
export class ErgebnisMockService {
    getErgebnisse() {
        return Promise.resolve(ERGEBNISSE);
    }
}

Component:

import { Component, OnInit } from '@angular/core';
import { ErgebnisMockService } from "../shared/mocks/ergebnis.mock.service";

@Component({
    moduleId: module.id,
    selector: 'ergebnisse',
    templateUrl: 'ergebnisse.component.html',
    styleUrls: ['ergebnisse.component.css'],
    providers: [ErgebnisMockService]
})
export class ErgebnisseComponent implements OnInit {
    ergebnisse: any;

    constructor(private ergebnisService: ErgebnisMockService) {
    }

    ngOnInit() {
        this.getErgebnisse();
    }

    getErgebnisse() {
        this.ergebnisService.getErgebnisse().then(data => this.ergebnisse = data);
    }

}

I get the following error in my console: ORIGINAL EXCEPTION: TypeError: Cannot read property 'Bereich' of undefined (The property does exist on the mocked object.)

If I return my mock-Object without the promise, everything works as expected. (Like so:)

   getErgebnisseWithoutPromise() {
        return ERGEBNISSE;
    }

If I console.log my Object after resolving it, I get the mock-object as expected:

getErgebnisse() {
        this.ergebnisService.getErgebnisse().then(
            data => {
                this.ergebnisse = data;
                console.log(this.ergebnisse);
            }
        );
    }

returns:

Object {Bereich: Array[3]}
>Bereich:Array[3]
>__proto__:Object`

What am I doing wrong here?

Thanks a lot!

Upvotes: 1

Views: 92

Answers (1)

Thierry Templier
Thierry Templier

Reputation: 202196

In fact, your object is loaded asynchronously even if your promise is resolved directly. So if you use the following in your template, you will have a problem because the ergebnisse is undefined at the beginning:

{{ergebnisse.Bereich}}

You should use the Elvis operator to prevent from this. In your case, something like that:

{{ergebnisse?.Bereich}}

To expand a bit more, Jake Archibald summarizes well the root cause of your problem:

Once a promise settles, or if it has already settled, it queues a microtask for its reactionary callbacks. This ensures promise callbacks are async even if the promise has already settled.

(from https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules)

The following link could give you more details:

Upvotes: 1

Related Questions