3

I have a function that consists of a for a loop. Loop runs for a certain time and after that returns a value. my only aim is to return the value, once the loop runs entirely. I tried with Promise and Async-Await but none of them work for me.

Async Function

async function getTotalQuestion(tag, question) {
    var output = [];
    for (let i = 0; i < question; i++) {
        getOne(tag).then((data) => {
                output.push(data);
            })
            .catch((err) => {
                console.log(err);

            })
    }
    return output;
}

calling of the async function

getTotalQuestion('eco', 9).then((data) => {
        question = data; //here data is coming as undefined
    })
    .catch((err) => {
        console.log(err)
    })
halfer
  • 19,824
  • 17
  • 99
  • 186
Pranay kumar
  • 1,983
  • 4
  • 22
  • 51

2 Answers2

4

The problem in the above code is that it does not wait for getOne to push data into the output array. In order to get the correct output, you'll have to await the result of getOne inside the for loop.

async function getTotalQuestion(tag, question) {
    var output = [];
    for (let i = 0; i < question; i++) {
        try {
            var data = await getOne(tag);
            output.push(data);
        } catch (err) {
            console.log(err);
        }
    }
    return output;
}
Rahul Bhobe
  • 4,165
  • 4
  • 17
  • 32
Kunal Kukreja
  • 737
  • 4
  • 18
  • Yeah. The way I like to think about it is, imagine that `getOne` takes a long time, like 30 seconds to give you a result. In the original code, when `i === 0` it'll start that 30 second process but not wait for it to finish and instead proceed to `i === 1`, etc. etc. – Adam Zerner Feb 21 '21 at 07:48
  • thanks, @kunal. it works. just one doubt, getOne is already a promise, promise itself an async method. it has to wait isn't it – Pranay kumar Feb 21 '21 at 07:49
  • 1
    @Pranaykumar Promise is a value that might resolve or reject in the future (with the stress on the future). Therefore, whenever a function returns a Promise, it might return a value (resolve) or throw an error (reject) but after it has completed processing. Now, in order to use the function's return value, one must explicitly wait (using `await` or `then`) for the it to finish it's task(s) and provide the required output. – Kunal Kukreja Feb 21 '21 at 07:57
0

If each getOne() call is independent of the other and can be called in any sequence, then you can use Promise.all() to asynchronously call multiple getOne() calls. Then await for all of them to complete before returning the total result from getTotalQuestion().

async function getTotalQuestion(tag, question) {
    try {
        return await Promise.all(Array(question).fill(0).map(_ => getOne(tag)));
    } catch (err) {
        console.log(err);
    }
}

If the order of calls to getOne() matter, then obviously the other answer posted works and you should await for each call in a for loop. Read more about Promise.all(). And learn more about the difference between Promise.all() and multiple await calls in this stack overflow post.

Rahul Bhobe
  • 4,165
  • 4
  • 17
  • 32