Angular Dependency Injection In Depth-Async Dependency Resolution

Async Dependency Resolution

In this blog post, we will explore async dependency resolution using Angular’s APP_INITIALIZER feature. We’ll demonstrate this in the context of a todo management app by fetching task data asynchronously from the JSONPlaceholder API.

First, let’s define the TodoService and ApiService:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Todo } from "../models/todo.model";

@Injectable({
  providedIn: "root",
})
export class TodoService {
  private todos: Todo[] = [];

  constructor(private apiService: ApiService) {}

  getAllTodo(): Todo[] {
    return this.todos;
  }

  // Rest of the methods...
}

api.service.ts

@Injectable({
  providedIn: "root",
})
export class ApiService {
  private apiUrl = "https://jsonplaceholder.typicode.com/todos";

  constructor(private http: HttpClient) {}

  fetchTodo(): Promise<Todo[]> {
    return this.http.get<Todo[]>(this.apiUrl).toPromise();
  }
}

In this example, the TodoService depends on the ApiService to fetch task data. The getAllTodo() method simply returns the todos stored in the TodoService. The ApiService uses Angular’s HttpClient to make a GET request to the JSONPlaceholder API and fetches the task data as a promise.

Next, let’s configure the APP_INITIALIZER in the app module:

import { NgModule, APP_INITIALIZER } from "@angular/core";
import { HttpClientModule } from "@angular/common/http";
import { TodoService } from "./services/task.service";
import { ApiService } from "./services/api.service";

// Function to fetch todos and initialize the TodoService
export function fetchTodoFactory(apiService: ApiService, todoService: TodoService): () => Promise<void> {
  return () => apiService.fetchTodo()
    .then((todos: Todo[]) => {
      todoService.setTodos(todos);
    });
}

@NgModule({
  imports: [
    HttpClientModule,
    // Other module imports...
  ],
  providers: [
    TodoService,
    ApiService,
    {
      provide: APP_INITIALIZER,
      useFactory: fetchTodoFactory,
      deps: [ApiService, TodoService],
      multi: true,
    },
  ],
  // Other module configurations...
})
export class AppModule {}

In this updated app module, we define a fetchTodoFactory function that takes the ApiService and TodoService as dependencies. This function is responsible for fetching the todos from the API and initializing the TodoService with the fetched data.

We then provide this function as part of the APP_INITIALIZER provider. The APP_INITIALIZER is an Angular feature that allows us to execute initialization tasks before the app starts. By using this provider, we ensure that the fetchTodoFactory function is executed during app initialization.

When the app initializes, the fetchTodoFactory function is called, which in turn calls the fetchTodo() method of the ApiService to fetch the todos. Once the todos are fetched successfully, the setTodos() method of the TodoService is called to store the todos locally.

This way, the TodoService is initialized with the fetched todos before the app starts, and the getAllTodo() method can return the todos as expected.

By using APP_INITIALIZER, we can handle async dependency resolution and ensure that the necessary data is fetched and available before the app starts, providing a seamless experience to the users of the task management app.

And here’s the sequence diagram representing the flow of events:

AppModulefetchTodoFactoryApiServiceTodoServiceHttpClientJSONPlaceholderApp initializationCall fetchTodoFactoryCall fetchTodo()Make GET request to JSONPlaceholderFetch todosReturn todosReturn todosCall setTodos()Todos are stored locallyResolve promiseResolve promiseAppModulefetchTodoFactoryApiServiceTodoServiceHttpClientJSONPlaceholder
Next Post Previous Post
No Comment
Add Comment
comment url