benjaminjosephw
benjaminjosephw

Reputation: 4417

How to call promise function recursively

I am trying to call an asynchronous function recursively using javascript promises but haven't found a pattern that works.

This is what I imagine would work:

var doAsyncThing = function(lastId){
  new Promise(function(resolve, reject){
    // async request with lastId
    return resolve(response)
  }
}

var recursivelyDoAsyncThing = function(lastId){
  doAsyncThing(lastId).then(function(response){
    return new Promise(function(resolve, reject){
      //do something with response
      if(response.hasMore){
        //get newlastId
        return resolve(recursivelyDoAsyncThing(newLastId));
      }else{
        resolve();
      }
    });
  });
}

recursivelyDoAsyncThing().then( function(){
  console.log('done');
});

Why doesn't this work? What have I misunderstood?

Is there a better pattern to solve this problem?

Upvotes: 5

Views: 3364

Answers (3)

Mayur Shedage
Mayur Shedage

Reputation: 1037

I have a simple example of recursive promise. The example is based on calculation factorial of number.

let code = (function(){
	let getFactorial = n =>{
		return new Promise((resolve,reject)=>{
			if(n<=1){
				resolve(1);
			}
			resolve(
				getFactorial(n-1).then(fact => {
					return fact * n;
				})
			)
		});
	}
	return {
		factorial: function(number){
			getFactorial(number).then(
				response => console.log(response)
			)
		}
	}
})();
code.factorial(5);
code.factorial(6);
code.factorial(7);

Upvotes: 2

Bergi
Bergi

Reputation: 664195

You're missing a return in the recursivelyDoAsyncThing function. Also you should avoid the Promise constructor antipattern:

function recursivelyDoAsyncThing(lastId) {
  return doAsyncThing(lastId).then(function(response) {
//^^^^^^
    //do something with response
    if (response.hasMore) {
      //get newlastId
      return recursivelyDoAsyncThing(newLastId);
    } else {
      return; // undefined? Always return a useful value
    }
  });
}

Upvotes: 2

Matt
Matt

Reputation: 44058

recursivelyDoAsyncThing needs to return a Promise in order to continue the chain. In your case, all you need to do is have doAsyncThing return its Promise:

var doAsyncThing = function(lastId){
  // Notice the return here:
  return new Promise(function(resolve, reject){

Then add return to your doAsyncThing call like so:

var recursivelyDoAsyncThing = function(lastId){
  // Notice the return here:
  return doAsyncThing(lastId).then(function(response){

Upvotes: 3

Related Questions