最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AsyncAwait not working as expected with Promise.all and a .map function - Stack Overflow

programmeradmin1浏览0评论

I have a slew of async functions I'm using and I'm having a weird issue.

My code, working, looks like:

async mainAsyncFunc (metadata) {
  let files = metadata.map(data => this.anotherAsyncFunc(data.url));
  return Promise.all(files);
}

anotherAsyncFunc function looks like:

  async anotherAsyncFunc (url) {
    return await axios({
      url,
    }).then(res => res.data)
      .catch(err => {
      throw err;
    });
  }

My issue comes when I try to append more data to what the first function (mainAsyncFunc) returns. My thoughts are to do that in the map, naturally, and when all is said and done, modified it looks like:

async mainAsyncFunc (metadata) {
    files = metadata.map(data => {
        return new Promise((resolve) => {
          let file = this.anotherAsyncFunc(data.download_url);
          let fileName = data.name;
          resolve({
            file,
            fileName
          });
        });
      });
    return Promise.all(files);
}

If it's not clear, I'm getting the file itself like normal, and appending a fileName to it, then resolving that object back.

For some reason, this is returning a pending Promise, whereas I would expect it to wait for them to be fulfilled and then returned as a complete file and name in an object. Any help understanding what I'm doing wrong would be greatly appreciated.

I have a slew of async functions I'm using and I'm having a weird issue.

My code, working, looks like:

async mainAsyncFunc (metadata) {
  let files = metadata.map(data => this.anotherAsyncFunc(data.url));
  return Promise.all(files);
}

anotherAsyncFunc function looks like:

  async anotherAsyncFunc (url) {
    return await axios({
      url,
    }).then(res => res.data)
      .catch(err => {
      throw err;
    });
  }

My issue comes when I try to append more data to what the first function (mainAsyncFunc) returns. My thoughts are to do that in the map, naturally, and when all is said and done, modified it looks like:

async mainAsyncFunc (metadata) {
    files = metadata.map(data => {
        return new Promise((resolve) => {
          let file = this.anotherAsyncFunc(data.download_url);
          let fileName = data.name;
          resolve({
            file,
            fileName
          });
        });
      });
    return Promise.all(files);
}

If it's not clear, I'm getting the file itself like normal, and appending a fileName to it, then resolving that object back.

For some reason, this is returning a pending Promise, whereas I would expect it to wait for them to be fulfilled and then returned as a complete file and name in an object. Any help understanding what I'm doing wrong would be greatly appreciated.

Share Improve this question edited Apr 3, 2017 at 21:30 Felix Kling 816k180 gold badges1.1k silver badges1.2k bronze badges asked Apr 3, 2017 at 20:51 ZachZach 5,07310 gold badges34 silver badges54 bronze badges 6
  • 2 async functions return promises. Nor can you turn a Promise-wrapped value into an ordinary value, you will always have to await or call .then. Why did you expect to get an array? – Jared Smith Commented Apr 3, 2017 at 20:56
  • @JaredSmith I use Promise.all() because I'm mapping over a dataset and returning the result of async function for each item. Thus creating an array. However, I just solved my own issue and am posting a solution now – Zach Commented Apr 3, 2017 at 20:58
  • Promise.all returns a Promise. Again, you cannot 'unwrap' a promise. You can only .then it. – Jared Smith Commented Apr 3, 2017 at 20:58
  • @JaredSmith I can assure you my working code is returning an array of fulfilled objects :). If it helps you understand it better, I call this function like: FileRetriever.mainAsyncFunc(metadata).then(contents => ...), and with my new working code contents is an array. – Zach Commented Apr 3, 2017 at 21:01
  • No, its not, your code does not work the way you seem to think it does. await is sugar over .then. You cannot ever unwrap a promise. Its a logical impossibility in the general case, as there is no way to tell if a promise is resolved or not. – Jared Smith Commented Apr 3, 2017 at 21:06
 |  Show 1 more comment

2 Answers 2

Reset to default 13

It looks like you've solved your issue, just as a bit of a pointer, you can further simplify your code as follows:

async anotherAsyncFunc (url) {
    return (await axios({ url })).data;
}

async mainAsyncFunc (metadata) {
    let files = metadata.map(async data => ({
        file: await this.anotherAsyncFunc(data.download_url),
        fileName: data.name
    }));

    return Promise.all(files);
}

Just solved the issue:

  files = metadata.map(async (data) => {
    let file = await this.anotherAsyncFunction(data.download_url);
    let fileName = data.name;
    return {
      file,
      fileName
    };
  });

I needed to wrap the anonymous function in async so I could use await inside of it. Hopefully this helps anyone else with a similar problem!

发布评论

评论列表(0)

  1. 暂无评论