首页 > 解决方案 > 使用 forkjoin 顺序上传文件块并在触发下一个 api 调用之前等待响应

问题描述

我有以下一段代码,基本上我正在尝试将大文件的块上传到从服务返回的签名 url..

只有在返回的 forkjoin 中的所有 PUT 请求都已完成后,我才需要调用 uploadcompleted 端点,但我面临的问题是我无法等待将块上传到签名的 url。

我在这里做错了什么?任何帮助将不胜感激。提前致谢。

filechunks(chunk: any, uploadUrls: string[], index) {
    let observableBatch = [];

    const headers: HttpHeaders = new HttpHeaders({
      'content-type': 'application/json'
    });
    observableBatch.push(this._http.put<any>(uploadUrls[index], chunk, { headers }))
    return forkJoin(observableBatch).pipe(delay(1000));
    // const createRequest = () => of(this._http.put<any>(uploadUrls[index], chunk, { headers }));
    // return forkJoin(createRequest).pipe(delay(1000));
  }

uploadfileinchunks(uniqueFileId: string, uploadId: string, chunks, uploadUrls): Observable<any> {
    let response = [];

    chunks.map( (chunk, i) => {
      let response = this.filechunks(chunk, uploadUrls, i).toPromise();
      console.log(response) 
    });


    const params = {
      some-id: some-id
    };

    return this._http.post<FileData>(
      `${somurl}/uploadcompleted`,
      {},
      {  {}, params }
    );
  }

标签: javascriptangularpromiserxjsobservable

解决方案


解释:

您的代码实际上没有意义,因此很难弄清楚您甚至要尝试做什么

filechunks(chunk: any, uploadUrls: string[], index) {
  const headers: HttpHeaders = new HttpHeaders({
    'content-type': 'application/json'
  });

  // observableBatch is an array of size 1. Why bother?
  const observableBatch = [];  
  observableBatch.push(
    this._http.put<any>(
      uploadUrls[index], 
      chunk, 
      { headers }
    )
  );

  // You're runnung forkJoin on a single observable? Again, why?
  return forkJoin(observableBatch).pipe(delay(1000));
}

uploadfileinchunks(uniqueFileId: string, uploadId: string, chunks, uploadUrls): Observable<any> {
  
  // Here, response is declared, but it's never used. You can delete this.
  let response = [];

  // chunks#map is a mapping function, but you're mapping every element to
  // null. Maybe what you mean is forEach?
  chunks.map( (chunk, i) => {
    // This a new response, this one is a promise. If you want the result
    // returned from filechunks, you'd need to resolve this promise
    // with response.then(LAMBDA) or await response
    // Also, mixing observables and promises is often a code smell.
    let response = this.filechunks(chunk, uploadUrls, i).toPromise();
    // You're logging a promise object here, not its resolved value
    console.log(response) 
  });

  // Not sure what this is?
  const params = {
    some-id: some-id
  };

  // call the uploadcompleted endpoint, but you haven't waited 
  // for your other calls to complete. That's what this question is about.
  return this._http.post<FileData>(
    `${somurl}/uploadcompleted`,
    {},
    {  {}, params }
  );
}

我对你打算做什么的最好猜测:

我显然无法对此进行测试,而且它还是不完整的,因为您的问题很模糊,但是也许这会引导您走上正确的道路?

请记住,uploadfileinchunks返回一个 Observable 并且 observables 在你之前不会做任何事情subscribe。因此,无论在何处调用此代码,您都需要确保这样做。

filechunks(chunk: any, uploadUrls: string[], index) {
  return this._http.put<any>(
    uploadUrls[index], 
    chunk, 
    { 
      headers: new HttpHeaders({
        'content-type': 'application/json'
      })
    }
  ).pipe(
    delay(1000)
  );
}

uploadfileinchunks(uniqueFileId: string, uploadId: string, chunks, uploadUrls): Observable<any> {

  return forkJoin(chunks.map(
    (chunk, i) => this.filechunks(chunk, uploadUrls, i)
  ).pipe(
    map(response => ({
      some-id: "some-id"
    })),
    switchMap(params => this._http.post<FileData>(
      `${somurl}/uploadcompleted`,
      {},
      {  {}, params }
    ))
  );
}

推荐阅读