【问题标题】:Pass data from server side to client side Angular Universal将数据从服务器端传递到客户端 Angular Universal
【发布时间】:2019-08-07 02:04:38
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: angular angular-universal


    【解决方案1】:

    新建一个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());
    

    这可能不是最干净的解决方案,但它确实有效。

    将上面的BrowserTransferStateModuleTransferHttpInterceptorService添加到app.module.ts

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

    【讨论】:

    • Harvix,是否可以缓存 POST api 请求?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    相关资源
    最近更新 更多