Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Out of Reject promise recursion in Javascript

Suppose I have this function below:

var a = 0;
function test () {
  return new Promise(function (resolve, reject) {
    a++;
    if (a < 10) {
      test()
      reject(a)
    } else {
      resolve(a)
    }
  })
}

test().then(function (a) {
  console.log('resolve', a)
}).catch(function (a) {
  console.log('reject', a)
})

It prints:

reject 10

I expect that it will print reject 1 ... 10.

How can I achieve this?

like image 590
Radonirina Maminiaina Avatar asked Sep 04 '20 09:09

Radonirina Maminiaina


People also ask

What does a rejected Promise return?

The Promise. reject() method returns a Promise object that is rejected with a given reason.

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.

What to do with Promise JavaScript?

It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.

Why use promises in JavaScript?

Promises are used to handle asynchronous operations in JavaScript. They are easy to manage when dealing with multiple asynchronous operations where callbacks can create callback hell leading to unmanageable code.


1 Answers

The reason you only see the one result is that nothing uses or reports the results of the recursive calls to test, just the first one. You need to move the reporting logic, and the increment logic:

var a = 0;
function test () {
    doOne(a++).then(function (a) {
    //     ^^
      console.log('resolve', a)
      if (a < 10) {
        test(); // Keep going
      }
    }).catch(function (a) {
      console.log('reject', a)
      if (a < 10) {
        test(); // Keep going
      }
    })
}

function doOne (a) {
  return new Promise(function (resolve, reject) {
    if (a < 10) {
      reject(a)
    } else {
      resolve(a)
    }
  })
}

test()

But note that unless you change your if (a < 10) check, it'll show resolve 10 not reject 10 at the end.

It's also worth noting that nothing in your code is asynchronous except the calls to the promise settlement handlers (because those calls are always asynchronous). Promises are used to report the completion and result of asynchronous processes. There's no reason to use them for synchronous processes.

Or here's another approach that avoids using a variable that's global to the code, waits for a previous promise to settle before moving on to the next one (which may or may not be what you want), makes it possible to know when the overall operation is complete, and avoids repeating the a < 10 logic:

function test(a) {
    return doOne(a).then(function (a) {
      console.log('resolve', a)
    }).catch(function (a) {
      console.log('reject', a)
      return test(a + 1);
    });
}

function doOne(a) {
  return new Promise(function (resolve, reject) {
    if (a < 10) {
      reject(a)
    } else {
      resolve(a)
    }
  })
}

test(0)
.finally(() => {
  console.log("Done");
});

Note that that one relies on the fact that we only want to continue when doOne rejects its promise.

like image 154
T.J. Crowder Avatar answered Sep 22 '22 15:09

T.J. Crowder