2

How will i write a promise function that recursively calls itself? What i ended up is like the one below.

function myPromiseFunction(input) {
    return new Promise(function(resolve, reject) {
        //compute something with input and got new input so again calling
        //myPromiseFunction
        if (newInput) {
            return myPromiseFunction(new input);
        }
        else {
            resolve(output);
        }
    });
}
myPromiseFunction(input).then(function(output) {
    console.log("completed processing data with input" );
});

Nothing is logged when i run the code. What am i doing wrong here?

Amit
  • 53
  • 7
  • What you have done is correct. What is `input`? Can you show a minimal reproducible example? Also, make sure that you add a rejection handler as well – thefourtheye Oct 01 '15 at 11:22
  • @thefourtheye - don't be so sure about that being correct – Jaromanda X Oct 01 '15 at 11:24
  • @JaromandaX Can you please point out what is actually wrong? – thefourtheye Oct 01 '15 at 11:25
  • @thefourtheye answer below beat me to it – Jaromanda X Oct 01 '15 at 11:26
  • @JaromandaX It is a better way to do this, but this pattern also will work – thefourtheye Oct 01 '15 at 11:27
  • @thefourtheye - no it will not. – Jaromanda X Oct 01 '15 at 11:30
  • @thefourtheye - consider the following: bare bones of question logic: `new Promise(function(resolve, reject) { return Promise.resolve('broken');}).then(console.log.bind(console));` bare bones of answer logic: `new Promise(function(resolve, reject) { resolve(Promise.resolve('works'));}).then(console.log.bind(console));` – Jaromanda X Oct 01 '15 at 11:36
  • Please show us what exactly *`compute something`* is - it, and only it, should be the promise-creating part. Do everything else, including the recursive call, in the `then` callback. – Bergi Oct 01 '15 at 12:30
  • 1
    @thefourtheye No, it is not correct at several levels, and it won't work. Most basically, the return from within the callback will do absolutely nothing--he needs it to be a call to resolve. –  Oct 01 '15 at 14:06
  • Ah I think I see it. A `return` in `Promise` constructor will not resolve the promise. Thanks @JaromandaX and torazaburo for explaining :-) – thefourtheye Oct 02 '15 at 02:28
  • thanks for the help guys – Amit Oct 02 '15 at 09:35

2 Answers2

3

Don't use explicit construction.

If you have to use it, resolve assimilates promises passed into it:

function myPromiseFunction(input) {
    return new Promise(function(resolve, reject) {
        //compute something with input and got new input so again calling
        //myPromiseFunction
        if (newInput) {
            resolve(myPromiseFunction(newInput)); // will wait for inner promise
        }
        else {
            resolve(output);
        }
    });
}

Quoting the specification:

The resolve function that is passed to an executor function accepts a single argument. The executor code may eventually call the resolve function to indicate that it wishes to resolve the associated Promise object. The argument passed to the resolve function represents the eventual value of the deferred action and can be either the actual fulfillment value or another Promise object which will provide the value if it is fulfilled.

Community
  • 1
  • 1
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • I like the word "assimilates". –  Oct 01 '15 at 11:38
  • I agree not to use explicit construction; how would one avoid doing that in this case? –  Oct 01 '15 at 11:55
  • @torazaburo I didn't pick it, likely [@Domenic](http://stackoverflow.com/users/3191/domenic) (in https://promisesaplus.com/ ). I can help with converting it if I knew what the actual code is - sort of like your answer. – Benjamin Gruenbaum Oct 01 '15 at 11:58
  • That document uses "assimilate" for something else, which is turning objects with a `then` method into a real promise. The term that spec seems to be using for this case is "make a promise **adopt** a state". –  Oct 01 '15 at 14:08
  • Yeah, this is essentially the same thing though. What `resolve` does is adopt the promise state of the promise passed to it. – Benjamin Gruenbaum Oct 01 '15 at 14:15
  • 1
    Right, I know, I was just commenting on terminology. –  Oct 01 '15 at 14:36
0

I'm assuming that "compute something with input" is the asynchronous part of this flow, and that it returns a promise resolving to [output, newInput]. Please correct me if this assumption is wrong.

You don't need a constructor at all. Rather than constructing promise after promise and then resolving it with the results of other promises, you can simply say:

function getOutput(input) {
  return computeSomething(input) .
    then(([output, newInput]) => newInput ? getOutput(newInput) : output);
}