服务器端呈现不等待API调用完成

时间:2017-11-08 05:36:56

标签: angular angular-universal

您好我使用的是Angular 4.3版,我已经实现了本文中提到的服务器端呈现。

https://medium.com/@cyrilletuzi/angular-server-side-rendering-in-node-with-express-universal-engine-dce21933ddce

当我点击服务器url以使服务器端呈现HTML时,组件的初始数据确实出现,这些数据是静态的,不依赖于任何API调用。

但问题是渲染不包含完成AJAX请求后应该存在的数据。

我已经在我的组件的 ngOnInit 方法中编写了API调用。它调用一个服务,该服务调用angular的http服务的get方法来获取数据。 角度通用渲染确实调用此函数。呼叫已作出,但不等待响应返回。它改为返回初始数据。 在服务器控制台中一段时间​​后,我确实看到响应已经回到服务器。但到那时,角度普遍已经回归。

请帮助解决此问题。

1 个答案:

答案 0 :(得分:1)

我知道这个问题已经存在了一段时间。这就是我们在LastCall.cc中使用解析器(虽然性能不高)找到解决方法的方法

import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import {
  Resolve,
  RouterStateSnapshot,
  ActivatedRouteSnapshot
} from '@angular/router';
import { makeStateKey, TransferState } from '@angular/platform-browser';
import { SearchService } from '@app/services/search.service';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';

@Injectable()
export class ProductDetailsResolver implements Resolve<any> {
  private result: any;
  constructor(
    private readonly state: TransferState,
    private search: SearchService
  ) { }

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> {
    const id = route.paramMap.get('dealId');
    const RESULT_KEY = makeStateKey<any>('product-details-resolver.result' + id);
    if (this.state.hasKey(RESULT_KEY)) {
      const res = of(this.state.get<any>(RESULT_KEY, null));
      this.state.remove(RESULT_KEY);
      return res;
    } else {
      this.state.onSerialize(RESULT_KEY, () => this.result);
      return this.search.searchDealById(id)
        .do(result => {
          this.result = result;
        }).catch((error) => {
          console.log('API Error --> ', error);
          this.result = {};
          return Observable.of({});
        });
    }
  }
}

上面的服务可以是任何异步数据获取程序,只要它返回Observable

StateTransfer握手将强制解析器等待API结果。问题是,没有超时,并且如果您的API出现任何问题,对于最终用户来说好像是挂了。

以下是使用解析器实现路由的方法:

path: 'campaigns',
children: [
  {
    path: ':dealId',
    component: EcommerceProductDetails,
    resolve: { result: ProductDetailsResolver },
    runGuardsAndResolvers: 'paramsOrQueryParamsChange'
  }
]

这是如何在组件中获取数据:

ngOnInit() {
  this.route.data.subscribe(data => {
    this.deal = <IDeal>data.result._source;
  });
}