Ленивая загрузка сервисов
ВАЖНО: Для работы ленивой загрузки сервис должен предоставляться автоматически. Декорируйте его с помощью @Injectable({providedIn: 'root'}) или @Service(). Без автоматического предоставления Angular не сможет создать сервис после его загрузки.
Функция injectAsync в Angular позволяет загружать сервис по запросу, только когда он действительно нужен. Это полезно, если сервис зависит от большой библиотеки или редко используемой функции и вы не хотите платить за её загрузку при первоначальной загрузке страницы.
При использовании injectAsync ваш сборщик выносит код сервиса в отдельный фрагмент JavaScript, который загружается при первом запросе экземпляра. После загрузки Angular разрешает сервис через обычную систему DI, поэтому он по-прежнему может зависеть от других внедряемых зависимостей и ведёт себя как любой другой синглтон.
Ленивое внедрение сервиса
Представьте ReportExporter, который зависит от тяжёлой библиотеки для работы с электронными таблицами. Большинство пользователей открывают отчёт, и лишь немногие нажимают Экспорт. Загружайте модуль экспорта по запросу:
import {Component, injectAsync} from '@angular/core';
@Component({
selector: 'app-report',
template: `<button (click)="export()">Export</button>`,
})
export class Report {
private exporter = injectAsync(() => import('./report-exporter').then((m) => m.ReportExporter));
async export() {
const exporter = await this.exporter();
exporter.export();
}
}
Первый вызов this.exporter() запускает динамический импорт и разрешает сервис из DI. Последующие вызовы используют тот же промис, поэтому фрагмент загружается только один раз.
Если лениво загружаемый сервис экспортируется по умолчанию, передайте динамический импорт напрямую, и Angular извлечёт default за вас:
@Service()
export default class ReportExporter {
/* … */
}
private exporter = injectAsync(() => import('./report-exporter')); Предварительная загрузка зависимости
По умолчанию ленивый фрагмент загружается только при вызове возвращённой функции. Вы можете начать загрузку раньше, передав в параметрах prefetch триггер. Триггер — это любая функция, возвращающая Promise; когда он разрешается, Angular запускает загрузчик.
В Angular есть встроенный триггер onIdle, который ожидает, пока браузер перейдёт в режим ожидания:
import {Component, injectAsync, onIdle} from '@angular/core';
@Component({
/* … */
})
export class Report {
private exporter = injectAsync(() => import('./report-exporter').then((m) => m.ReportExporter), {
prefetch: onIdle,
});
}
Вы также можете настроить onIdle, указав максимальное время ожидания, чтобы предварительная загрузка всегда выполнялась в пределах заданного интервала, даже на загруженных страницах:
injectAsync(loader, {prefetch: () => onIdle({timeout: 1_000})});
ПРИМЕЧАНИЕ: Предварительная загрузка выполняется при наличии возможности. Если пользователь вызовет функцию до запуска предварительной загрузки, Angular всё равно немедленно загрузит зависимость и разрешит ваш await, как только она будет готова.
Настройка собственного триггера предварительной загрузки
PrefetchTrigger — это просто функция, возвращающая промис; загрузчик запускается сразу после его разрешения. Используйте её, чтобы согласовать предварительную загрузку с собственными сигналами, например наведением курсора или тактом планировщика:
import {PrefetchTrigger} from '@angular/core';
export function onHover(target: HTMLElement): PrefetchTrigger {
return () =>
new Promise<void>((resolve) => {
target.addEventListener('pointerenter', () => resolve(), {once: true});
});
}
Super-powered by Google ©2010–2025.
Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0.
https://angular.dev/guide/di/lazy-loading-services