Последовательно загружать фрагменты файлов с помощью forkjoin и ждать ответа перед запуском следующего вызова api

#javascript #angular #promise #rxjs #observable

#javascript #angular #обещание #rxjs #наблюдаемый

Вопрос:

У меня есть следующий фрагмент кода, в основном я пытаюсь загрузить фрагменты большого файла на подписанные URL-адреса, возвращаемые из службы..

Мне нужно вызвать конечную точку uploadcompleted только после завершения всех запросов PUT в возвращенном forkjoin, но проблема, с которой я сталкиваюсь, заключается в том, что я не могу дождаться загрузки фрагментов на подписанный 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 }
    );
  }
 

Комментарии:

1. this.filechunks(chunk, uploadUrls, i).toPromise(); это будет выполняться асинхронно, и uploadfilechunks запустит post немедленно, не дожидаясь

Ответ №1:

Интерпретация:

Ваш код на самом деле не имеет смысла, поэтому трудно понять, что вы даже пытаетесь сделать

 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 возвращает наблюдаемый объект, а наблюдаемые объекты ничего не делают до тех пор, пока вы 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 }
    ))
  );
}