Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async recursive using promise

So i am trying to transfer my code into the "Promise world", and in many places when i had to "loop" with async functionality - i simply used recursion in such a way

function doRecursion(idx,callback){
    if(idx < someArray.length){
        doAsync(function(){
            doRecursion(++idx,callback)
        });
    }else{
        callback('done!')
    }
}
doRecursion(0,function(msg){
    //...
});

Now i am trying to make the change into the Promise world, and i am quite stuck

var Promise = require('bluebird')
function doRecursion(idx){
    return new Promise(function(resolve){
        if(idx < someArray.length){
            doAsync(function(){
                //... doRecursion(++idx)
                // how do i call doRecusion here....
            });
        }else{
            resolve('done!')
        }
    });
}
doRecursion(0).then(function(msg){
    //...
});

Thanks.

like image 867
yosiweinreb Avatar asked Feb 22 '16 12:02

yosiweinreb


People also ask

Can we use async with promises?

Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

How is a promise used in a recursive function?

This is the function that will be called recursively. Set the starting record location for the query based on the ExclusiveStartKey. Call the DynamoDB scan function. The promise() method “promisifies” the scan function to return a Javascript Promise.

Can we use promise and async await together?

Async/Await is used to work with promises in asynchronous functions. It is basically syntactic sugar for promises. It is just a wrapper to restyle code and make promises easier to read and use. It makes asynchronous code look more like synchronous/procedural code, which is easier to understand.

Are recursive functions asynchronous?

The getSentenceFragment function and recursive call to getSentence are now asynchronous, so require the await keyword. And that's it! Note, you may only use await within an async function, so in order to invoke this function, you still need to use promises: getSentence() .


2 Answers

I'd go with the Promise.all approach.

What this does is wait until all the promises in the array have resolved. The map will apply the async method to each item in the array and return a promise.

function doAsyncP() {
    return new Promise((resolve) => {
        doAsync(function() {
            resolve();
        });
    });
}

Promise.all(
    someArray.map(doAsyncP)
).then((msg) => {
    //we're done.
});
like image 146
Ben Fortune Avatar answered Sep 25 '22 13:09

Ben Fortune


In your recursive function, you can do this:

...
if (idx < someArray.length) {
  doAsync(function() {
    resolve(doRecursion(idx + 1));
   });
} else {
...

In other words, while idx is less than someArray.length, your promise will resolve to another promise, this time the promise returned by calling doRecursion() with an idx incremented by one. The then callback the bottom will not be called until doRecursion resolves to some value other than a promise. In this case, it will eventually resolve with a value of 'done!'.

That said, if you are using promises, you probably don't need to use recursion at all. You might have to refactor your code a bit more, but I would suggest considering @BenFortune's answer as an alternative.

like image 45
McMath Avatar answered Sep 24 '22 13:09

McMath