如何拦截调用并动态返回 JSON 文件(没有 "import")

How to intercept call and serve back JSON file dynamically (without "import")

我有一个文件夹和 json 文件的脚手架来模拟 API 的路径。当我 运行 npm run start:mockLocalMockInterceptor 被配置时,例如通过本地 Folder A/Folder B/C.json[=31 的 http 调用替换对 host/A/B/C 的调用=]. JSON 文件由超出此处范围的单独脚本生成。我不能像许多教程那样使用 "import",因为我需要一个通用的解决方案,因为我正在模拟的 API 会随着时间的推移而发展(文件夹和文件的脚手架也会如此)。

/**
 * The idea is to only build this into the bundle if we specify so (e.g. on TeamCity, on your localhost), where you don't want to rely
 * on external resources for development
 * No conditionals in the code bundle! No configuration files or database dependency.
 */
import {
  HttpInterceptor,
  HttpResponse,
  HttpHandler,
  HttpRequest,
  HttpEvent,
  HttpClient,
  HttpHeaders
} from '@angular/common/http';

import { Injectable, Injector } from '@angular/core';
import { Observable, of } from 'rxjs';
import { ErrorService } from './error.service';

const devAssetsFolder = 'assets';

@Injectable()
export class LocalMockInterceptor implements HttpInterceptor {
  constructor(
    private errorService: ErrorService,
    private injector: Injector,
    private http: HttpClient
  ) {}
  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    if (request.url.endsWith('.json')) return next.handle(request);
    console.log(
      ` >>> Mock Interceptor >>> ${request.url} has been intercepted`
    );
    const path = `${devAssetsFolder}${request.url}.json`;
    var promise = this.getJSON(path).toPromise();
    const jsonheaders = new HttpHeaders();
    jsonheaders.set('Content-Type', 'application/json');
    let json2;
    promise
      .then(json => {
        console.log(json);
        json2 = json;
      })
      .catch(error => console.log(error));
    Promise.all([promise]);
    console.log(json2);
    return of(
      new HttpResponse({ status: 200, body: json2, headers: jsonheaders })
    );
  }

  private getJSON(jsonPath: string): Observable<any> {
    return this.http.get(jsonPath);
  }
}
  • 第一个条件是避免无限循环,因为我在拦截器中发送 HTTP 请求
  • 根据URL得到JSON文件的路径很自然
  • 在我看来,我必须将 JSON Observable 转换为一个 promise,这样我就可以等待它完成,然后再将 json 重新包装到返回的 Observable 中.然而,在调试时,似乎 Promise.all 没有等待承诺完成(json2 在下一行未定义),我最终发送了一个空的 http 正文......

    1. 如何修复此 rxjs 承诺?
    2. 内部 HTTP 调用是我唯一的选择吗?
    3. 有没有办法不依赖承诺?你能想出更好的方法来实现这个目标吗?
  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    if (request.url.endsWith('.json')) return next.handle(request);
    console.log(
      ` >>> Mock Interceptor >>> ${request.url} has been intercepted`
    );
    const path = `${devAssetsFolder}${request.url}.json`;
    return this.getJSON(path).pipe(map(result => {
      const jsonheaders = new HttpHeaders({ 'Content-Type': 'application/json' });
      return 
        new HttpResponse({ status: 200, body: result, headers: jsonheaders });
    }), // you can also add catchError here
    );
  }

在拦截方法中,您可以 return 一个可观察对象。所以你的 getJSON 方法 return 是一个可观察的,我们添加了一个映射函数,它将结果映射到新的 http 响应。如果您的响应已经正确 headers 您甚至不需要管道和映射函数,您可以这样做:

 return this.getJSON(path); // it's an observable, so it's OK.

您是否尝试过在拦截器中修改目标 URL?你想做一个 API 调用 return 一些 JSON 但不是调用动态 API,你只是想调用你静态服务器所以它可以 return预定义JSON.

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const fakeUrl = `${devAssetsFolder}${request.url}.json`;
    const fakeRequest = request.clone({url: fakeUrl});
    return next.handle(request);
  }