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: