[ $davids.sh ] — david shekunts blog

⏲ Go Defer in JS ⏲

# [ $davids.sh ] · message #178

Go Defer in JS

In Go, there is a very cool defer operator that allows you to postpone the execution of any operation until the end of a function (regardless of whether it's a return or an error thrown at the current or lower levels)

For example, closing access to a database when exiting a function where it was opened would look something like this:


db := pg.connect() defer db.destroy()

// A bunch of logic and if there's a return or an error thrown, db.destroy() will be executed // ...

I've always regretted that JS didn't have such an operator, but I've finally found an alternative, and it's try ... finally ...

It seems obvious, but for some reason, I never thought of it, so the above example would be:


const db = pg.connect() try { // A bunch of logic and if there's a return or an error thrown, db.destroy() will be executed // ...
} finally { db.destroy() }

Not as elegant, but it provides the ability to execute an operation 100% when exiting a function

I've made a gist with tests

  • @ Gennadii IT-K Khotovytskyi · # 535

    The idea is great, but you need to be careful with return in finally, as the value will be returned from it, even if try or catch returns something. (We once caught a strange, hard-to-reproduce bug in production, it turned out someone had an early return in the finally logic))

    const finallyTest = () => {
      try {
        console.log("try");
        return "success";
      } catch (error) {
        console.log("catch");
        return "error";
      } finally {
        console.log("finally");
        return "finally";
      }
    };
    
    const fromFinallyTest = finallyTest();
    console.log(fromFinallyTest);
    

    By the way, the TypeScript team is working on allowing resource management (creation/disposal) in one place, which should be available soon. https://devblogs.microsoft.com/typescript/announcing-typescript-5-2-beta/#using-declarations-and-explicit-resource-management

  • @ [ $davids.sh ] · # 536

    We've added highlighting for unsafe returns in this case in the linter so we don't mess up 😉

  • @ [ $davids.sh ] · # 538

    I was just asked this today, and I think I found the simplest and clearest answer: a Promise in JS is the same as the Future Trait from Rust.

  • @ [ $davids.sh ] · # 539

    It's hard to explain clearly