Exploring Angular's APP_INITIALIZER: Comparing Promises and Observables

I have implemented an Angular v4 application where I need to retrieve settings from the server before the app starts. This is achieved using the APP_INITIALIZER:

{
  provide: APP_INITIALIZER,
  useFactory: initializeSettings,
  deps: [SettingsService],
  multi: true
}

export function initializeSettings(config: SettingsService) {
   return () => config.loadOne();
}

//import declarations    
@Injectable()
export class SettingsService {
  constructor(private http: HttpClient) { }

  loadOne(): Promise<boolean> {
    return new Promise<boolean>((resolve) => {
        this.http.get('url').subscribe(value => {
            console.log('loadSettings FINISH');
            resolve(true);
        });
    });
  }

  loadTwo(): Observable<any> {
    const promise = this.http.get('url');

    promise.subscribe(value => {
        console.log('loadSettings FINISH');
    });

    return promise;
  }
}

In my application, there is a function called manageSettings() that requires the data from the SettingsService service be initialized.

When utilizing the loadTwo() function, the app does not wait for it to complete:

app-root constructor
manageSettings()
loadSettings FINISH

However, when using the loadOne() function, everything works as expected:

loadSettings FINISH
app-root constructor
manageSettings()

It's puzzling why this discrepancy occurs. Can someone shed some light on this situation?

Answer №1

Angular 12 has introduced support for Observables, eliminating any issues for users of Angular 12 or newer.

The main difference between why load_one works and load_two doesn't is due to the fact that Angular versions 11 and below only wait for Promises, not Observables.

You can find the original source code here:

if (this.appInits) {
    for (let i = 0; i < this.appInits.length; i++) {
        const initResult = this.appInits[i]();
        if (isPromise(initResult)) {
            asyncInitPromises.push(initResult);
        }
    }
}

The function isPromise is defined as follows:

export function isPromise<T = any>(obj: any): obj is Promise<T> {
    // allow any Promise/A+ compliant thenable.
    // It's up to the caller to ensure that obj.then conforms to the spec
    return !!obj && typeof obj.then === 'function';
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In TypeScript, what is the return Type of sequelize.define()?

After hearing great things about TypeScript and its benefits of static typing, I decided to give it a try. I wanted to test it out by creating a simple web API with sequelize, but I'm struggling to understand the types returned from sequelize. Here ar ...

The TypeScript factory design pattern is throwing an error stating that the property does not

While working with TypeScript, I encountered an issue when trying to implement the factory pattern. Specifically, I am unable to access child functions that do not exist in the super class without encountering a compiler error. Here is the structure of my ...

Gathering adorned categorizations (sans any listed category divisions)

My current setup involves an event dispatcher class that triggers listeners on specified occurrences. I've successfully implemented registering event listeners via decorators, but I feel like there may be a better solution out there. At the moment, e ...

Can someone confirm if I am importing this png file correctly? I am encountering an error with Vite, here is my code

Error: TypeScript+ React + Vite [plugin:vite:import-analysis] Failed to find import "./assets/heropic.png" in "src\components\Hero.tsx". Are you sure the file exists? Hello fellow developers! I am new to working with react and typescript. Curren ...

Is it possible to use the conditional (ternary) operator within the [ngClass] directive in Angular2 while also including multiple class conditions?

Would it be possible to combine multiple conditions with ternary operator, like in the following example that currently doesn't work? <div [ngClass]="{'checked': isChecked, 'disabled': isDisabled, isEmpty ? 'empty-class&ap ...

How to Retrieve the Current Item in *ngFor Loop Using TypeScript in Angular 4

In my JSON file, I have an array containing 5 people. Each person in the array has a list of items associated with them. In my HTML code, I am using *ngFor to iterate over the people and display their names. Additionally, I want to display the total sum of ...

Angular: Variable `app` has not been defined

I am working on a simple MEAN stack app and it is almost up and running, but I encountered an uncaught reference error when it tries to redirect to the index page. The server seems to be running fine and the browser displays "Loading..." as expected on the ...

Validation messages in Angular only display once the form has been reset using the reset

I am having trouble with my form appearing clean without validation error messages after using the reset() function. Initially, my form looks clean as expected: https://i.sstatic.net/HLKPq.png However, if a user clicks the register button and encounters a ...

Guide on storing geolocation information in an array on Google Firebase Realtime Database using Angular HttpClient

I have been working on developing an innovative Android geolocation tracking app using Ionic with the assistance of the Cordova Geolocation plugin. The tracking feature has been successfully implemented thus far. However, I am currently facing challenges w ...

Is there a way for me to retrieve the bodyHeight attribute of ag-grid using public variables or data?

Working on a project using ag-grid community react. The main feature is a scrollable section filled with data, which can range from one piece to millions of pieces. I'm also incorporating a footer component for the grid that needs to adjust its height ...

Utilizing the split function within an ngIf statement in Angular

<div *ngIf="store[obj?.FundCode + obj?.PayWith].status == 'fail'">test</div> The method above is being utilized to combine two strings in order to map an array. It functions correctly, however, when attempting to incorporate the spli ...

Step-by-step guide on deploying an app folder containing both Backend and Frontend folders to Heroku

I recently developed a new app named my-folder-book, which consists of two folders known as my-folder-front and my-folder-back. These folders are built using React and NodeJS. Could someone please assist me with uploading this app folder? I am having trou ...

Avoid redundant GET requests in your Angular application initialization by utilizing RxJS

Is there a way to consolidate multiple http requests into one in Angular or RxJS, if they are triggered closely together? For instance, when I open my application, all 20 components call the same http request in their ngOnInit method: I have implemented ...

What is the process for finding GitHub users with a specific string in their name by utilizing the GitHub API

I'm looking to retrieve a list of users whose usernames contain the specific string I provide in my query. The only method I currently know to access user information is through another endpoint provided by the GitHub API, which unfortunately limits t ...

How can I use JavaScript to update the content inside HTML tags with a specific string?

I have a situation where I need to replace a string in two different ways Input: Parameters-->string, AnnotationName, input Case 1: And I should input <i>Annotaion</i> as <b>input</b> Output : { displayData: `And I should inp ...

What kind of type is recommended to use when working with async dispatch in coding?

For my TypeScript and React project, I am currently working on an action file called loginAction.tsx. In this file, there is a specific line of code that handles the login functionality: export const login = (obj) => async dispatch => { dispatch( ...

Changing the left border color dynamically based on the value of an object within a loop

My objective is to achieve a design where the left border of the cards appears as shown in the image below: The loop structure is as follows: <ion-card *ngFor="let office of searchItems" class="custom"> Ideally, I would like to ...

Styling does not affect an Angular component that is injected into an iframe

I am facing an issue with styling in an iframe when trying to append my own angular component. Despite various attempts, I have been unsuccessful in getting the styling to apply to the component within the iframe. Upon loading the iframe, I use JavaScript ...

Setting up `ng serve` to detect changes in a containerized Angular 2 application

Currently, I am 'dockerizing' an existing Angular 2 application that is being run on angular-cli version 1.0.0-beta.31. I am facing difficulties in configuring ng serve to automatically reload my app whenever a file in the working directory is u ...

Breaking down the steps to flip between two images when clicked in Vue.js

I'm currently trying to implement a feature in Vue.js where images switch on click. The functionality I'm aiming for is as follows: Upon initial load, the image displays in black, then upon clicking/selecting it, the image transitions into a blu ...