【问题标题】:make API call before another on angular interceptormake API call before another on angular interceptor
【发布时间】:2022-12-02 01:14:09
【问题描述】:

In my app I have multiple forms where the result JSON object may vary in its structure and has nested objects and arrays in different levels. These forms also allow the user to upload files and the object stores and array with url to download, name, etc.

What I do now is turn the file into base64 string, then before any request that has files, I upload them to my backend.

What I want to do is to make that API call of file upload, wait until it finish and once I get response, modify the user's body request, only then make the main post request with these modifications. But is not pausing, the queries are being executed in parallel, I know this because in the backend the fileisuploaded but the user's object is not modified, and besides for some reason the query of file upload is being executed several times for no reason.

export class FilesCheckerInterceptor implements HttpInterceptor {

  constructor(private filesService: FilesService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const data = request.body;
    if (data) {
      
      const uploaded: File[] = [];
      this.traverse(data, files => {
        files.forEach(file => {
          const base64 = file.data;
          const result = this.filesService.toFile(base64, file.name);
          uploaded.push(result);
        });
      });
      
      console.log(request);

      return this.filesService.uploadFile(uploaded).pipe(
        mergeMap(response => {
          this.traverse(data, files => {
            for (let i = 0; i < response.length; i++) {
              files[i] = response[i];
            }
          });
  
          return next.handle(request.clone({ body: data }));
        }),
      );      
    }
    else {      
      return next.handle(request);
    }
  }

  traverse(obj: any, action: (value: InternalFile[]) => void) {
    if (obj !== null && typeof obj === 'object') {
      Object.entries(obj).forEach(([key, value]) => {
        if (key === 'attachments' && Array.isArray(value)) {
          // const files = value as InternalFile[];
          action(value);
        }
        else {
          this.traverse(value, action);
        }
      })
    }
  }
}

【问题讨论】:

    标签: angular typescript rxjs


    【解决方案1】:

    I will suggest using forkJoin.

    forkJoin will wait for all passed observables to emit and complete and then it will emit an array or an object with the last values from corresponding observables. This operator is best used when you have a group of observables and only care about the final emitted value of each. One common use case for this is if you wish to issue multiple requests on page load (or some other event) and only want to take action when a response has been received for all. In this way, it is similar to how you might use Promise.all.

    Or you can use async-await.

    Further explanation on forkjoin https://ultimatecourses.com/blog/rxjs-forkjoin-combine-observables

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多