noa-dev noa-dev - 3 months ago 23
Javascript Question

Recursion-like behaviour in a Promise chain

I am currently struggling with the implementation of a recursion to a specific Promiseblock.

I abstracted my code down to this to provide an example:

function x(){
return new Promise((resolve, reject)=>{
return resolve(2)
})
}

var testvar = 0

x()
.then(result => {
// simulating mongodb request which returns another promise
return new Promise(resolve => {resolve()})
})
.then(result => { // BLOCK START
// simulating another operation
testvar += 1
return new Promise(resolve => {resolve()})
})
.then(result => {
// some other operations

if(testvar < 2){
// RERUN PROMISE FROM BLOCK START
console.log("pls recurse")
}else{
// some other operation
return new Promise(resolve => {resolve()})
}
// BLOCK END
})
.then(result => {
// continue
console.log("foo")
})
.catch(err => console.log(err))



// classic approach

function y(){
// something
// Operation 1
// Operation 2
if(x != 1 ){
y() // recurse
}else{
// continue
}
}


Now what I want this code to do is to run the Promisechain one after the other till the last one (the one which logs "foo"). UNLESS testvar is smaller than 2, then I want the Function from "// BLOCK START" to be executed again until testvar is greater or equal 2.

I am relying on this Promisebased build because I am making some asynchronous function calls to a helper library and a mongodb which returns promises.

Code can also be tested in a fiddle

If something is unclear feel free to ask - I will gladly try to precise my question.
Thank you for your help.

Answer

There is not a big difference to a normal recursive function. You would move your code into a runBlock function, and in your if condition you either call the return runBlock(result); again or your return your resolved Promise:

function x() {
  return new Promise((resolve, reject) => {
    return resolve(2)
  })
}

var testvar = 0

function runBlock(result) {

  testvar += 1
  return new Promise(resolve => {
      resolve()
    })
    .then(result => {
      // some other operations

      if (testvar < 2) {
        console.log('testvar < 2');
        // RERUN PROMISE FROM BLOCK START
        return runBlock(result);
      } else {
        console.log('testvar >= 2');
        // some other operation
        return new Promise(resolve => {
          resolve()
        })
      }
      // BLOCK END
    })
}


x()
  .then(result => {
    // simulating mongodb request which returns another promise
    return new Promise(resolve => {
      resolve()
    })
  })
  .then(runBlock)
  .then(result => {
    // continue
    console.log("foo")
  })
  .catch(err => console.log(err))


function a(a) {
  return new Promise(resolve => {
    resolve(a)
  })
}

// classic approach

function y() {
  // something
  // Operation 1
  // Operation 2
  if (x != 1) {
    y() // recurse
  } else {
    // continue
  }
}