What is the difference between then and finally in a promise?

后端 未结 3 1443
故里飘歌
故里飘歌 2021-01-01 19:14

I see the docs for Bluebird\'s finally but I still don\'t quite understand the difference vs. then.

To be clear: I know exactly why then ge

相关标签:
3条回答
  • 2021-01-01 19:37

    All right, after some chatting and a lot of help from KevinB, I figured out at least one difference. Consider the following two new tests:

    function test5 () {
        console.log("REJECT + THEN + CATCH/THROW + THEN");
        return new Promise((resolve, reject) => reject(new Error("rejected")))
           .then(() => console.log("then"))
           .catch(function(err) { throw new Error("error in catch"); })
           .then(() => console.log("end"));
    }
    
    function test6 () {
        console.log("REJECT + THEN + CATCH/THROW + FINALLY");
        return new Promise((resolve, reject) => reject(new Error("rejected")))
           .then(() => console.log("then"))
           .catch(function(err) { throw new Error("error in catch"); })
           .finally(() => console.log("end"));
    }
    

    In these the promise is rejected, but an error is thrown from catch.

    The promise ends up ultimately rejected in both cases but for the finally case the finally is still executed, the then is not.

    So that's the difference. They're almost the same with the sole exception that when an error is thrown from the catch handler, finally executes, and then does not.

    This means the comment I quoted also does have merit: If in my error handler another error occurred, a then wouldn't guarantee clean-up, but a finally would. That's the case I was missing.

    0 讨论(0)
  • 2021-01-01 19:39

    First difference: Sometimes you don't want to catch errors at the place they arise, but in the code that uses this function, so you don't catch them. In that case you can't substitute then() and finally().

    Sometimes you have to clean something up whether there was an error or not (nulling references, clearing timeouts ... stuff like that). That's where you use finally().

    Second difference: The function you pass to catch() could also throw, then you would have a rejected Promise and the following then() would not be called.

    (so a finally before a catch will still execute on an error, didn't know that)

    Yeah, that's the point of finally(). It will be executed under any circumstance without changing the resolved value.

    You might want to read/google a bit about try {} finally {}, without catch.

    0 讨论(0)
  • 2021-01-01 19:51

    .then and .finally are not the same.

    .then is the main promise primitive. It's what is defined, thoroughly, in the Promises/A+ spec and all promise libraries will implement it.

    A Bluebird .finally handler will "be called regardless of the promise's fate". So an unhandled exception still triggers a .finally.

    new Promise((resolve, reject) => reject(false))
      .finally(a => console.log('finally', a))
    // finally undefined
    // Unhandled rejection false
    
    new Promise((resolve, reject) => reject(false))
      .then(a => console.log('then', a))
    // Unhandled rejection false
    

    .finally won't change the resolved value of the promise and doesn't receive the result of the promise chain.

    new Promise((resolve, reject) => reject(false))
      .catch(e => {
        console.log(e)
        return 2
      })
      .finally(a => {
        console.log('finally', a)
        return 1
      })
      .then(res => console.log('res', res))
    // finally undefined
    // res 2
    

    The methods look similar in your test cases as the tests catch all errors and you are only using promises for flow control, not relying on the values being resolve/rejected along the promise chain.

    0 讨论(0)
提交回复
热议问题