1

I am trying to figure out if it's possible to use promises instead of a standard callback in a recursive function.

The way I have it now:

function recursive(data, cb){

     (function promiseProvider(data){

          return newThenable(data).then(function(val){
                 if(val.a){
                    cb(null, val);
                 }
                 else {
                    return promiseProvider(val);
                 }

          });

     })(data);

}

This works, but I can't figure out how I could make a pure promise implementation.

Perhaps this would work?

  function recursive(data){

      return newThenable(data).then(function(val){
               if(val.a){
                  return // <<< ???
                 }
                 else {
                   return recursive(val);
                 }

        });

     }

However, that doesn't work.

2
  • What happens if something goes wrong and .a is never set? Commented Nov 11, 2016 at 9:39
  • 1
    "return // <<< ???", " LOL no that doesn't work..." Yes, that pattern should return expected result. After first call to recursive, return value from recursive is a Promise, as .then() returns a new Promise object. Commented Nov 11, 2016 at 9:44

3 Answers 3

5

Given you were calling the callback with val as the result argument, just

return val;

from the then callback. That's it.

function recursive(data){
     return newThenable(data).then(function(val){
         if (val.a){
             return val;
         } else {
             return recursive(val);
         }
     });
 }
Sign up to request clarification or add additional context in comments.

4 Comments

That approach would only return last val to .then() chained to recursive
@guest271314 Which is exactly what the OP is looking for?
Could be. The only reason to return val is if val object is not defined outside of scope of function calls. Interpreted Question as how to return accumulated results derived at each call. The accumulated results could be occurring presently at object val. If that is case and val is referencing an object inside of calls, yes, return val object. If object is originally defined outside scope of calls, and passed to recursive to begin process, it is not necessary to return val. OP could use return pattern at Question, then reference the object at chained .then()
@guest271314 There's nothing about accumulation in the question, so I'd rather not assume that.
3

Push val to an array. If val.a return array of results, else call recursive with val and array of accumulates results as parameter. See multiple, sequential fetch() Promise

  function recursive(data, results) {
    return newThenable(data).then(function(val) {
      if (val.a) {
        // results.push(val);
        return results
      } else {
        results.push(val);
        return recursive(val, results).catch(function(e) {console.log(e)});
      }
    });
  }

5 Comments

Where did you get that array from? The non-promise code didn't use one either.
You shouldn't have that .catch(function(e) {console.log(e)}) inside the function. It's the caller's obligation to catch errors.
@Bergi The array can be passed when recursive is called, or not passed at all, having been created before call to recursive
@Bergi There should not be an issue with .catch() inside function. Multiple .catch() functions can be used. Placed .catch() within function to illustrate that option; though could be removed without affecting pattern or result.
@guest271314 Ah, I had not considered where the empty array comes from, but that might be a problem as well, yeah. However, my comment was about the OP never using any arrays anywhere, not even in the callback-style code, so I wondered why you'd introduce that results array.
2

Nowadays the ES8 async/await makes it more readable. I skipped the try-catch for now.

async function recursive(data, results = []) {
    let val = await newThenable(data);
    if (val.a) {
        return results
    } else {
        results.push(val);
        return recursive(val, results);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.