4

我正在使用 TransferState 进行 SSR,并且想知道当我们这样做时谁保证

http.get(...).subscribe(data => {
  transferState.set(DATA_KEY, data)
})

数据将存储在transferState中?因为http.get 是异步操作,并且可以在没有这些数据的情况下生成内容并将其提供给客户端。

4

1 回答 1

9

Angular Zone 保证所有异步操作(由 zone.js 跟踪的调用)在渲染之前完成。

让我们来看看

服务器.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);
}); 

renderModuleFactory它只会在从函数返回的 promise(3) 被解决后才会发生。

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));
}

您可以在上面看到我们实际上通过platform.bootstrapModuleFactory(moduleFactory)(4)在这里运行 Angular 应用程序

_render function(5) 内部,应用程序等待引导完成

return moduleRefPromise.then((moduleRef) => {

之后我们可以看到答案的关键

return applicationRef.isStable.pipe((first((isStable: boolean) => isStable)))
        .toPromise()
        .then(() => {

您可以看到角度通用查看ApplicationRef.isStable observable 以了解何时完成渲染。简而言之,当Zone 没有安排微任务时触发 ApplicationRef 上的 isStable (7):

if (!zone.hasPendingMicrotasks) {
  try {
    zone.runOutsideAngular(() => zone.onStable.emit(null));

在此处输入图像描述

于 2018-12-25T16:48:47.257 回答