-1

i have a asynchronous function inside that am using forEach and promise.all. my question is how can i make the function stops until one of the value in forEach is rendered completely and then go for the next one.

sentingMailtoOneRestauarnt this is a large function and now am getting only partial values from this because next value in forEach is invoked before the completion of first one.

 exports.handler = async () => {

return fetchAllConnectedAcccounts(null).then((response) => {
    var promises_array = []
    response.forEach((data) => {
        if (data) {
            var promise = sentingMailtoOneRestauarnt(data, yesterday).then((resp)=>{
                promises_array.push(promise);

            })

        }
    })
    return Promise.all(promises_array).then((result) => {
        return result;
    })
}).catch((err) => {
    console.log(err)
});

}

DRS
  • 1
  • You need the good old `for of` loop here, `forEach` is synchronous and doesn't care about a returned promise or an async callback. – hazardous Dec 24 '19 at 10:42
  • No, forEach is sync. See here for example https://stackoverflow.com/questions/5050265/javascript-node-js-is-array-foreach-asynchronous – A Ralkov Dec 24 '19 at 10:47

2 Answers2

1

From the code, looks like you already are using async here. Skip ove promises -

const responses = await fetchAllConnectedAcccounts(null);
const results = [];
for (const response of responses){
 if (response){
   results.push(await sentingMailtoOneRestauarnt(response, yesterday));
 }
}

// do whatever with results...

hazardous
  • 10,627
  • 2
  • 40
  • 52
  • Are you sure you want call await from for? – svltmccc Dec 24 '19 at 10:49
  • Works like a peach! – hazardous Dec 24 '19 at 10:49
  • Next iteration of for will wait nothing even you call await, for this case esnext has `for await` – svltmccc Dec 24 '19 at 10:52
  • That's for async iterables, e.g. generators. `responses` is a normal array. See https://lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795/ – hazardous Dec 24 '19 at 10:53
  • I want to say OP needs to call next iteration only if previous iteration already completed but you solution don't work like expected behaviour, it's a mock of your solution https://jsfiddle.net/epdvr78x/ Maybe I don't understand the question – svltmccc Dec 24 '19 at 10:57
  • My understanding is that `sentingMailtoOneRestauarnt` is a costly call and the OP wants it to be finished before it's invoked again. Maybe we both don't understand the question – hazardous Dec 24 '19 at 11:00
  • I try to understand this part of the question: **my question is how can i make the function stops until one of the value in forEach is rendered completely and then go for the next one.** – svltmccc Dec 24 '19 at 11:02
  • 1
    Also, I fixed your fiddle, now it works as expected https://jsfiddle.net/7kmn0d3g/1/. The issue was that the `promise` was a single promise instance, which would only resolve once. A resolved promise stays resolved with the last resolved data, even if you await it again and again . – hazardous Dec 24 '19 at 11:10
0

Currently your array is full of resolved promises (you push to it only after promise is resolved).

exports.handler = async () => {

return fetchAllConnectedAcccounts(null).then((response) => {
    var promises_array = []
    response.forEach((data) => {
        if (data) {
            var promise = sentingMailtoOneRestauarnt(data, yesterday);
            promises_array.push(promise); // push to array before promise is resolved
        }
    })
    return Promise.all(promises_array); // wait for resolving here

    /*.then((result) => {
        return result;
    })*/ // unnecessary
}).catch((err) => {
    console.log(err)
});
A Ralkov
  • 1,046
  • 10
  • 19