0

I have downLoadFile function that returns Promise<File> and downloadFiles that asynchronously calls it multiple times.

  async downloadFile(id: number, name: string): Promise<File> {
    return new Promise<File>((resolve, reject) => {
      axios({
        url: `/file/${id}`,
        method: "GET",
        responseType: "blob",
      })
        .then((response) => {
          const file = new File([response.data], name);
          resolve(file);
        })
        .catch((error) => {
          reject(error);
        });
    });
  }
  async downloadFiles() {
    const res = await Promise.all([
      this.view1 ? this.downloadFile(this.view1.id, this.view1?.name) : null,
      this.view2 ? this.downloadFile(this.view2.id, this.view2?.name) : null,
      this.view3 ? this.downloadFile(this.view3.id, this.view3?.name) : null,
      this.extra_photos.map(async (photo) => {
        await this.downloadFile(photo.id, photo.name);//Promise<void>
      }),
    ]);
    //const a = await Promise.all(
    //  this.extra_photos.map(async (photo) => {
    //    await this.downloadFile(photo.id, photo.name);
    //  })
    //); void[]
    this.fileView1 = res[0] ?? undefined; //File | undefined
    this.fileView2 = res[1] ?? undefined; //File | undefined
    this.fileView3 = res[2] ?? undefined; //File | undefined
    this.filesExtraPhoto = res[3]; //Type 'Promise<void>[]' is not assignable to type 'File[]'.
  }

But when I call downloadFile in this.extra_photos.map, which inside of Promise.all, it returns Promise<void>, not File.

Then I rewrote my code to this, but got the same issue:

  async downloadFile(id: number, name: string): Promise<File> {
    const file = await axios({
      url: `/file/${id}`,
      method: "GET",
      responseType: "blob",
    });
    return new File([file.data], name);
  }
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Nikita
  • 15
  • 5
  • I think you are misunderstanding how promises work with async await. I came up with my version here but haven't tested https://gist.github.com/jrgleason/eeed880f430dfc75ccd4330645c9109f Let me know if that helps. – Jackie Jul 14 '23 at 04:40
  • Thank you for your option. It will help me better understand how to work with Promise and await. – Nikita Jul 14 '23 at 05:59
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! Your rewritten `downloadFile` is much better. – Bergi Jul 14 '23 at 15:58
  • @Bergi, yes, i agree that rewritten variant much better and cleaner, than first one. – Nikita Jul 17 '23 at 06:27

1 Answers1

1

You need to either add a return to your map callback or remove the braces. It is not currently returning a value. So all it is doing is await ing.

You also need to wrap the .map() in a Promise.all since it will return an array of promises. And what you want is a promise for an array.

Promise.all(this.extra_photos.map(async (photo) => {
    return await this.downloadFile(photo.id, photo.name);
})),
Promise.all(this.extra_photos.map(async (photo) =>
    await this.downloadFile(photo.id, photo.name)
)),
JLRishe
  • 99,490
  • 19
  • 131
  • 169