1

In my application, I have to upload a loop of images first to get the file ids from the system. After I got the ids I can upload the object.

async uploadFiles(token: string):Promise<number[]> {
    let ids = Array<number>();
    this.images.forEach((image: ImageData) => {
      this.fileService.uploadFile(image, token).subscribe((result: File) => {
        ids.push(result.data.id);
      })
    });
    return ids;
  }

The goal of this function is to return all the ids. But since the fileService has a subscribe, it will only return an empty array.

Matheus M.
  • 71
  • 6
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Heretic Monkey Feb 20 '21 at 14:37
  • Basically, you can't do it that way. You'll need to get the other arguments to the forEach function (index, array) and use those to see if you're on the last image in the images array, then resolve your promise with the ids. – Heretic Monkey Feb 20 '21 at 14:39
  • @HereticMonkey would it be a possibility to make the this.fileService to an other function and return it as a promise (async) and await in the forEach? – Matheus M. Feb 20 '21 at 14:44
  • You could just try appending `.toPromise()` instead of `.subscribe(...)`, and await that. You're likely better off creating an `uploadFiles` method on `fileService` that takes `this.images`. Make that method upload multiple files at once and return multiple ids. Depending on the service infrastructure, that could be easy, or difficult, but it would be more efficient than making many requests in a short time frame. – Heretic Monkey Feb 20 '21 at 14:52

2 Answers2

1

The problem here is that when you do fileService.uploadFile.subscribe(), this subscription is carried out out asynchronously. The subscription waits till it gets a result, meanwhile the execution of the lines after the subscription is carried out immedialely. So, the return ids is executed right after the subscription. At this point the result has no value and nothing is pushed into ids. So, it just returns empty array.

You can declare ids globally. So you can push into them when result is ready and can use the ids or you can make the this function return an observable and use subjects to provide the values. It is shown in the code below.

private idsSubject = new Subject<number[]>();

async uploadFiles(token: string):Observable<number[]> {  //made return type observable
    this.images.forEach((image: ImageData) => {
      this.fileService.uploadFile(image, token).subscribe((result: File) => {
        this.idsSubject.next(result.data.id);
      })
    });
    return this.idsSubject.asObservable();
  }

When you want the ids subscribe tho this function. Like uploadFiles('my string').subscribe((id)=>this.ids.push(id)) Try this, hope it helps. Tell me otherwise

0

you must return Observable and use switchMap for call second Api to upload.