I am stuck trying to build a recursive function that is already defined as a promise.
I have not been able to apply the recursive pattern on the code below which is looping only once even though loopFor
is initialised at 20
what I am missing?
Requirement: receivingMessages
must be a promise.
let globalMessageArray = [];
let count = 0;
let loopFor = 20;
function receivingMessages(params, loopFor, globalMessageArray) {
return new Promise((resolve, reject) => {
const command = new ReceiveMessageCommand(params);
client.send(command).then(
(data) => {
if (data && data.Messages && data.Messages.length) {
data.Messages.forEach(msg => {
globalMessageArray.push(msg);
});
};
return resolve(globalMessageArray);
},
(error) => {
return reject(error);
}).then(
(globalMessageArray) => {
count = count 1;
console.log("Loop Count: " count); // always returns 1
if (loopFor === 1) {
return resolve(globalMessageArray);
} else {
return resolve(receivingMessages(params, loopFor - 1, globalMessageArray));
};
});
});
};
CodePudding user response:
In the first then callback client.send(cmd).then(data => …
you return resolve(globalMessageArray)
. This effectively short-circuit your loop, because a promise can only resolve
once. Later call of resolve
has no effect.
client.send(cmd).then((data) => {
…
return globalMessageArray;
}, …
Remove first call to resolve
should solve your problem.
You said in comment:
Using async/await would imply to rewrite the whole program
No, your understanding of async/await is wrong. Any async function is automatically a promise returning function, which meets your requirement. Async/await is just syntax sugar on top of promise.
This means you can safely rewrite ONLY receivingMessages
function without needing to modify other places that call it.
Although there is nothing wrong with vanilla promise, rewriting to async/await will make your code so much cleaner.
async function receivingMessages(params, loopFor, globalMessageArray) {
const command = new ReceiveMessageCommand(params);
const data = await client.send(command);
if (data && data.Messages && data.Messages.length) {
data.Messages.forEach(msg => {
globalMessageArray.push(msg);
});
}
if (loopFor === 1) {
return globalMessageArray;
} else {
return receivingMessages(params, loopFor - 1, globalMessageArray)
};
};
CodePudding user response:
The issue with your code is that the resolve call in the then callback after the client.send promise resolves is returning the result of calling receivingMessages instead of the receivingMessages promise itself. This causes the recursive loop to only execute once.
To fix this, you can change the resolve call to return the result of calling receivingMessages directly:
return receivingMessages(params, loopFor - 1, globalMessageArray);
This will cause the receivingMessages function to be called in a recursive manner until loopFor reaches 1.
You may also want to consider adding a base case to the function to ensure that it terminates, such as adding a check for loopFor being less than or equal to 0 and returning the globalMessageArray in that case.