将数据从服务器端传递到客户端Angular Universal

时间:2019-08-05 16:08:44

标签: angular angular-universal

有一种方法可以在服务器端执行期间定义常量值(例如缓存的数据),并且在客户端执行时也可以使用?

它可以像缓存系统一样工作,该缓存是当应用程序在服务器端运行时生成的缓存。

例如,我有一个由我的api资源api/categories返回的类别列表。我想仅在服务器端运行时在我的应用程序的第一次调用中存储此请求的结果,并且此缓存的数据可在客户端使用,而无需再次请求api/categories。我怎样才能做到这一点?

我已经实现了BrowserModule.withServerTransition来将状态从服务器转移到客户端,它可以工作,但是真诚的我不了解它实际上是如何工作的。

那么..如何将我的角度应用程序的任意数据从服务器端传递到客户端端执行?

1 个答案:

答案 0 :(得分:2)

创建一个新的 TransferHttpInterceptorService

import {Injectable, Inject, PLATFORM_ID} from '@angular/core';
import {HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {tap} from 'rxjs/operators';
import {TransferState, makeStateKey, StateKey} from '@angular/platform-browser';
import {isPlatformServer} from '@angular/common';

@Injectable({
  providedIn: 'root'
})
export class TransferHttpInterceptorService implements HttpInterceptor {
  constructor(
    private transferState: TransferState,
    @Inject(PLATFORM_ID) private platformId: any) {
  }

  public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    if (request.method !== 'GET') {
      return next.handle(request);
    }

    const key: StateKey<string> = makeStateKey<string>(request.url);

    if (isPlatformServer(this.platformId)) {
      return next.handle(request).pipe(tap((event) => {
        this.transferState.set(key, (<HttpResponse<any>>event).body);
      }));
    } 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);
      }
    }
  }
}

此处注意:如果您在服务器上使用了其他主机或使用了相对路径,则需要将密钥更改为

const key: StateKey<string> = makeStateKey<string>(request.url.split("/api").pop());

这可能不是最干净的解决方案,但它可以工作。

从上面

BrowserTransferStateModule TransferHttpInterceptorService 添加到 app.module.ts

imports: [
    BrowserModule.withServerTransition({appId: 'serverApp'}),
    BrowserTransferStateModule, <--
    ...
]
providers: [
{
  provide: HTTP_INTERCEPTORS,
  useClass: TransferHttpInterceptorService,
  multi: true
},
...
]