Search code examples
angularjspromiseangularjs-scopeangular-promise

async function in $onInit not binding to HTML


async function in OnInit firing after template has loaded

Apologies if this has been asked. I couldn't seem to find something speaking to my specific scenario.

In my controller, I define an $onInit function that calls a function that that in turn calls an async function. The async function has a catch block that sets a boolean for an ng-if in the template (controls whether an error message should display):

controller:

$onInit() {
    initFn();
}

function initFn() {
    innerFn();
}

function innerFn() {
    asyncFn
        .then(() => { 
            // does some stuff 
        })
        .catch(() => { 
            boolVal = true;
        })
}

template:

<div ng-if="boolVal">some-error-message</div>

I test this by sending back a Promise.reject() for asyncFn but the error message doesn't show. boolVal, however, is true. What I think is happening is that the template compiles and builds before the async call is able to finish. How do I ensure that all API calls are completed in $onInit before the template has loaded? If that isn't the problem, what am I missing?

Thanks!


Solution

  • I test this by sending back a Promise.reject() for asyncFn

    The ES6 promises returned by Promise.reject() are not integrated with the AngularJS framework. Instead, return AngularJS promises:

    function asyncFn () {
        if (/* error condition */) {
            return $q.reject();
        };
    }
    

    AngularJS modifies the normal JavaScript flow by providing its own event processing loop. This splits the JavaScript into classical and AngularJS execution context. Only operations which are applied in the AngularJS execution context will benefit from AngularJS data-binding, exception handling, property watching, etc.1

    For more information, see


    what are common scenarios/services that I should be aware

    1. Beware of ES6 promises -- use AngularJS promises
    2. Beware of third-party promises -- use $q.when to convert to AngularJS promises
    3. Beware of async/await -- they return ES6 promises
    4. Beware of window.setTimeout - use the $timeout service
    5. Beware of window.setInterval -- use the $interval service
    6. Beware of jQuery.ajax -- use the $http service

    Event from outside the AngularJS framework

    1. Beware of element.addEventListener
    2. Beware of jQuery.on
    3. Beware of events from third-party APIs / libraries

    You can also use $apply() to enter the AngularJS execution context from JavaScript.

    Keep in mind that in most places (controllers, services) $apply has already been called for you by the directive which is handling the event. An explicit call to $apply is needed only when implementing custom event callbacks, or when working with third-party library callbacks.

    For more information, see