0

I have the following chain of promise, which I expected the resolve function of .finally() to be promise to be returned, but instead the last .then() is the one that gets returned.

exportReportToJson (url,opts) {
    const requestJSON = {
      "values" : []
    };

    return this.getValue(url)
    .then( value => {
      requestJSON.values.push(value);
      if(opts.extraValue){
        return this.getExtraValue(value);
      }else{
        return Promise.finally();
      }
    })
    //The index of .push gets returned instead
    .then(extraValue => requestJSON.values.push(extraValue))
    //But I want requestJSON to always be the returned Promise
    .finally( () => requestJSON)
}

As you can see I want finally to always be the final promise to be returned, is that not what is for? What am I missing here? I thought it worked as an .always()

No await please.

I want to have a conditional .then while not changing the final .then basically.

Mojimi
  • 2,561
  • 9
  • 52
  • 116
  • how about `.then( () => requestJSON)`? – Roland Starke Jan 14 '19 at 16:35
  • @RolandStarke I thought I couldn't since the .then() before doesn't return a promise in the resolve function – Mojimi Jan 14 '19 at 16:36
  • your just missing a return `.finally( () => return requestJSON;);` and a couple of `;`. Note this isn't a promise your returning, it's the result of the promise. Youl'll still need to handle this async – Liam Jan 14 '19 at 16:48
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Liam Jan 14 '19 at 16:49
  • 1
    @Liam one liner arrow function automatically returns without needing to type return – Mojimi Jan 14 '19 at 16:51
  • Fair enough. I'm pretty sure this is a duplicate anyway – Liam Jan 14 '19 at 16:52
  • What is this `return Promise.finally();`? – Bergi Jan 14 '19 at 20:06
  • Can you use `async`/`await` syntax? – Bergi Jan 14 '19 at 20:06
  • @Bergi well I thought that to skip to the .finally() I had to return Promise.finally() – Mojimi Jan 15 '19 at 11:32
  • @Mojimi No, you cannot just "skip" a stage. You could by throwing an exception and later catching it, but it's easier to move the `.then(extraValue => requestJSON.values.push(extraValue))` line inside the `if` statement, chaining it right to the `this.getExtraValue(value)`. – Bergi Jan 15 '19 at 12:35
  • @Bergi mind posting the solution as an answer? – Mojimi Jan 15 '19 at 12:38

2 Answers2

2

.finally does not let you change what the promise resolves as; it's just meant for doing teardown logic. If the promise resolved with some value, it remains resolved with that value; if it rejected with some value, it remains rejected with that value.

You can see more about its behavior here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally

If you need to change the value, then use .then or .catch. If you also want identical logic in both, then you'll need to use both. This either means duplicating the code, or extracting it to a named function.

Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • 1
    So what would be the solution? Make .finally return a .resolve? – Mojimi Jan 14 '19 at 16:30
  • @Mojimi you need finally just to know that it's completed. To handle value you need to use then/catch. – Danil Gudz Jan 14 '19 at 16:31
  • If you have one handler for each then just move it to separate function: `function handlePromise(response) {...}` and use it as `promise.then(handlePromise, handlePromise)`. But I'd suggest you to separate logic for errorHandling and successful response handling – Danil Gudz Jan 14 '19 at 16:32
0

There is no Promise.finally function. It seems like what you actually wanted is

function exportReportToJson (url,opts) {
  return this.getValue(url).then(value => {
    if (opts.extraValue) {
      return this.getExtraValue(value).then(extraValue => [value, extraValue]);
    } else{
      return [value];
    }
  }).then(values => {
    const requestJSON = {values};
    return requestJSON;
  });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375