2

I am using promises and async to wait for a web request to finish. The variable info is empty when displaying its value using console.log(infos);

I am unsure as to why and what I am doing wrong?

var processFruits = async () => {
    let infos = [];
    let fruits = ["apples", "pears", "bananas"]

    await fruits.forEach(async fruit => {
        let response = await getFruitInfo(fruit);
        infos.concat(response);
        console.log(response);
    });

    console.log(infos);
};

let getFruitInfo = (fruit) => new Promise((resolve, reject) => {
    fetch("https://www.fruitmap.org/api/trees", {
        method: 'GET',
    }).then(response => {
        if (response.ok) {
            resolve(response.json());
        } else {
            reject(error);
        }
    }).catch(error => {
        reject(error);
    });
});
Coder Guy
  • 185
  • 5
  • 12
  • Did you mean `infos = infos.concat(response);`? – loganfsmyth Jun 14 '19 at 15:31
  • https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it – SLaks Jun 14 '19 at 15:32
  • 1
    `forEach` doesn't work with async functions. Use a normal `for of` loop to run your promises sequentially or `Promise.all(...map...)` to run in parallel. – georg Jun 14 '19 at 15:33
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it) in `getFruitinfo`! – Bergi Jun 14 '19 at 15:48

2 Answers2

1

.forEach() doesn't return anything, so your outer await doesn't wait for anything.

You need to call .map(), which will return an array of the promises returned by the inner async callbacks. You then need to call Promise.all() to turn that array of promises into a single promise to await:

await Promise.all(array.map(async ...));
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
0

.concat doesn't modify your original reference but it creates a new one, that's why your infos array is still empty.

var processFruits = async () => {
    let infos = [];
    let fruits = ["apples", "pears", "bananas"]

    fruits.forEach(async fruit => {
        let response = await getFruitInfo(fruit);
        infos = infos.concat(response); // here
        console.log(response);
    });

    console.log(infos);
};

let getFruitInfo = (fruit) => new Promise((resolve, reject) => {
    fetch("https://www.fruitmap.org/api/trees", {
        method: 'GET',
    }).then(response => {
        if (response.ok) {
            resolve(response.json());
        } else {
            reject(error);
        }
    }).catch(error => {
        reject(error);
    });
});

processFruits();
Karim
  • 8,454
  • 3
  • 25
  • 33