如何使用 Angular 服务器端渲染的 Transfer State Service
假设我们使用 Angular Universal 开发一个服务器端渲染的 Angular 应用,这个应用会消费一个第三方的 Restful API.
上述场景分为下列六个步骤:
-
用户向部署了 Angular 服务器端应用的 Node.js 服务器发起页面请求
-
Node.js 调用第三方 Restful API,
-
第三方 Restful API 返回结果,这个结果被用于渲染最后的页面
-
服务器端渲染的页面,返回给浏览器
-
Angular 在浏览器中引导,并再次调用 Restful API
-
Restful API 返回给浏览器,Angular 客户端应用重新将数据渲染到视图中。
我们可以通过创建 TransferState 服务来提高应用程序的效率,该服务是在 Node.js 服务器和浏览器中呈现的应用程序之间交换的一个键值注册表。
我们将通过一个 HTTP_INTERCEPTOR 机制来使用它,该机制将驻留在 HttpClient 服务中,并将操纵请求和响应。
创建一个新的 class,实现 HttpInterceptor 接口定义的 intercept 方法:
@Injectable({
providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
每当对 HttpClient 服务执行任何 API 调用时,都会调用此方法。
为了简单起见,我们仅针对 GET 方法启用 TransferState:
if (request.method !== 'GET') {
return next.handle(request);
}
我们根据 GET 请求的 URL 生成一个密钥。 我们将使用键值对来存储或检索请求响应,具体取决于请求是在服务器端还是浏览器端处理:
const key: StateKey<string> = makeStateKey<string>(request.url);
为了区分服务器和浏览器运行环境,我们使用 @angular/common
库中的 isPlatformServer 方法以及 PLATFORM_ID 注入令牌:
if (isPlatformServer(this.platformId)) {
//serverSide
} else {
//browserSide
}
当服务器端渲染时,我们将 API 结果写入 Transfer State 注册表中:
if (isPlatformServer(this.platformId)) {
return next.handle(request).pipe(tap((event) => {
this.transferState.set(key, (<HttpResponse<any>> event).body);
}));
在浏览器端代码中,我们要检查给定 HTTP 请求的响应是否已经驻留在 Transfer State 注册表中。 如果存在,我们直接从注册表中取出值,并清除注册表,以便将来的调用可以存储新数据,并将响应返回给调用者。
当且仅当注册表中不存在给定的键,我们才在客户端环境下执行 HTTP 调用。
else {
const storedResponse = this.transferState.get<any>(key, null);
if (storedResponse) {
const response = new HttpResponse({body: storedResponse, status: 200});
this.transferState.remove(key);
return of(response);
} else {
return next.handle(request);
}
}
相关文章
- 数据透视表上线!如何在纯前端实现这个强大的数据分析功能?
- 怎么组织 Angular 项目 |Top 5 技巧
- angular框架如何实现父子组件传值、非父子组件传值
- Angular SSR 应用的 SEO 实现一个例子 - meta 和 title 元素的赋值
- 如何在Angular项目中使用MQTT
- Angular Universal Application 应该处理 HTTP POST 请求吗?
- Angular SSR 和 PWA 结合起来使用的一些现象观察
- angular框架发展史
- 关于 Angular 应用对浏览器 Back 按钮支持问题的讨论
- Angular 应用 tsconfig.json 文件里的 typeRoots 属性讲解
- MySQL Error number: 3739; Symbol: ER_SRS_INVALID_ANGULAR_UNIT; SQLSTATE: SR002 报错 故障修复 远程处理
- Angular 6.0 即将发布 承诺更小更快更易用
- 基于豆瓣API+Angular开发的webApp
- angular中使用路由和$location切换视图