hellouworld
hellouworld

Reputation: 605

When does the finally gets called in the js Promise context?

When does the finally gets called in the js Promise context?

I thought at first that the finally will be called after the last then. But then I understood that it is impossible to determine the last then. Also my attempt below proves that:

function f(resolve, reject) {
    resolve("foo");
};
var p = new Promise(f);
p.then(function(data) {
     console.log("data: " + data); 
});
p.finally(function(data) {
     console.log("in finally");
});
p.then(function(data) {
     console.log("data: " + data); 
});

Output:

data: foo
in finally
data: foo

So, the finally is not called after the last then. And I thought the the finally should be called after the resolve then. But in the example code I tried above we can see that it is also not the case (because the registered then was called between the resolve and the finally).

Hence, I am confused and can not understand when will the finally be called.

Upvotes: 4

Views: 3309

Answers (2)

mbojko
mbojko

Reputation: 14679

.finally complements then and catch: then block gets called on fulfillment, catch gets called on rejection, and finally gets called in both cases (for example: you make an API call, in then block you process the data, in catch block you display error message, in finally block you hide the loading spinner).

Then the chain continues.

Promise.reject('execute some action')
  .then(() => console.log('I\'ll handle success here'))
  .catch(() => console.log('error handling'))
  .finally(() => console.log('this block will be executed either way'))
  .then(() => console.log('and the adventure continues'))

Upvotes: 7

CertainPerformance
CertainPerformance

Reputation: 370929

None of your Promises are chained - everything is connected directly to the root p Promise. So when the p Promise resolves (or rejects), all .then and .finally callbacks attached to that Promise run, probably in the order in which they were attached.

In most situations, the Promises will be chained - (eg .then(() ... ).then or .then(() ... ).finally). Then, the finally would run after the previous .then completes, or after the previous .then throws:

function f(resolve, reject) {
    resolve("foo");
};
var p = new Promise(f);
p.then(function(data) {
     console.log("data: " + data); 
})
.finally(function(data) {
     console.log("in finally");
});

function f(resolve, reject) {
    resolve("foo");
};
var p = new Promise(f);
p.then(function(data) {
     console.log("data: " + data);
     console.log("About to throw");
     throw new Error();
})
.finally(function(data) { // Above Promise throws, so if this was a .then, it wouldn't run
     console.log("in finally");
});
// No .catch, so this results in an unhandled Promise rejection

When deciding when to execute, the .finally doesn't look ahead to see if anything is chained off of it - rather, the .finally callback executes as soon as the Promise it's called on resolves or rejects.

Upvotes: 1

Related Questions