Angular Zone гарантирует, что все асинхронные операции (вызовы, отслеживаемые zone.js) будут завершены до рендеринга.
Давайте посмотрим на
server.ts
app.get('*', (req, res) => {
res.render('index', { req });
});
||
\/
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
Мы видим, что все обычные маршруты используют универсальный движок для рендеринга html.
res.render
метод (1) определяет обратный вызов по умолчанию .Функция ngExpressEngine возвращает другую функцию с этим обратным вызовом , переданным в качестве параметра (2).Как только этот обратный вызов запущен, экспресс отправляет результат пользователю.
done = done || function (err, str) {
if (err) return req.next(err);
self.send(str);
};
Теперь давайте посмотрим, когда этот обратный вызов будет запущен .Как упоминалось ранее, нам нужно взглянуть на функцию ngExpressEngine.
getFactory(moduleOrFactory, compiler)
.then(factory => {
return renderModuleFactory(factory, {
extraProviders
});
})
.then((html: string) => {
callback(null, html);
}, (err) => {
callback(err);
});
Это произойдет только после разрешения обещания (3), возвращающегося из функции renderModuleFactory
.
renderModuleFactory
Функция может быть найдена в @ angular / platform-server
export function renderModuleFactory<T>(
moduleFactory: NgModuleFactory<T>,
options: {document?: string, url?: string, extraProviders?: StaticProvider[]}):
Promise<string> {
const platform = _getPlatform(platformServer, options);
return _render(platform, platform.bootstrapModuleFactory(moduleFactory));
}
Вы можете видеть выше, что мы фактически запускаем приложение Angular здесь через platform.bootstrapModuleFactory(moduleFactory)
(4)
Внутри _render приложение функции (5) ожидает завершения начальной загрузки
return moduleRefPromise.then((moduleRef) => {
и после этого мы можем увидеть ключ дляответ:
return applicationRef.isStable.pipe((first((isStable: boolean) => isStable)))
.toPromise()
.then(() => {
Вы можете видеть, что угловой универсальный взгляд на ApplicationRef.isStable , наблюдаемый, чтобы знать, когда закончить рендеринг.Проще говоря, isStable on ApplicationRef запускается, когда Зона не имеет запланированных микрозадач (7):
if (!zone.hasPendingMicrotasks) {
try {
zone.runOutsideAngular(() => zone.onStable.emit(null));