How to Execute Something else after the Return Statement in Javascript
TW
Tech Wizard
Author
Jan 19, 2025
3 min read

How to Execute Something else after the Return Statement in Javascript

1
I recently had a problem where I needed to send an email to a customer after they placed an order. The process was to await the database creation of the order and if successful send an email confirmation message. While I could have separated this into two functions, I needed to use-server and I am using typescript, which also makes passing the order data to the send Email function problematic.
Therefore, my implementation was to have a function create an order and then call the send email function with the order, before returning to the client. This made creating orders a slow process. I opted to change this since sending an email is not of immediate need that getting the response on whether the order has been created succesfully.

In JavaScript, the return statement immediately terminates the execution of a function. However, there are situations where you might want to perform additional actions after the return statement has been encountered, even though it seems counterintuitive. This is generally achieved through asynchronous operations or using specific mechanisms like try...catch...finally blocks.

I found three methods to achieve this.

Method 1: try...catch...finally

The finally block of a try...catch statement always executes, regardless of whether an exception is thrown or not. This provides a reliable way to execute code after a return statement within the try block.

function myFunction() {
  try {
    return "Value from try block";
  } catch (error) {
    console.error("Error:", error);
  } finally {
    console.log("This always executes after the return statement.");
  }
}

console.log(myFunction()); 
// Output: "Value from try block", 
// Followed by 
//"This always executes after the return statement."

This has its limitations since we only want to send the email after the order creation has been successful. We can counter this by using a variable to track whether the function has thrown an error before sending the email, but this is not a good practice.

function createOrder() {
    let isError= false
    try {
        const order = await db.create()
        return order
    } catch (error) {
        console.error("Error:", error);
        isError = true
        throw new Error(error)
    } finally {
        if (!isError) {
            await sendEmail()
        }
    }
}

One problem I faced with this setup is that sendEmail relies on the returned order object data from the try block and passing it around became problematic.

Method 2: setImmediate()

setImmediate() (available in Node.js and some browser environments) schedules a callback function to be executed after the current event loop iteration completes. This ensures that the callback runs after the function containing the  return statement has finished its synchronous execution.

function myFunction() {
  setImmediate(() => {
    console.log("This executes after the return statement.");
  });
  return "Value from myFunction";
}

console.log(myFunction()); 
// Output: "Value from myFunction",
//"This executes after the return statement."

Method 3: setTimeout()

Similar to setImmediate(), setTimeout() Schedules a callback function to be executed after a specified delay (in milliseconds). While introducing a small delay, it offers a more widely compatible approach for browsers and Node.js.

function myFunction() {
 setTimeout(() => {
    console.log("This executes after the return statement (with a delay).");
  }, 0); // 0 milliseconds delay
  return "Value from myFunction";
}

console.log(myFunction()); 
// Output: "Value from myFunction",
//"This executes after the return statement (with a delay)." 

Important Note: The order of execution in the setImmediate() and setTimeout() examples might seem unexpected at first. The key is understanding that the return statement concludes the synchronous part of the function. The callbacks scheduled by setImmediate() or setTimeout() are executed asynchronously, later in the event loop.

In conclusion, I found the setImmediate() implementation to be a lot faster in execution as it helps return the function return statement very early before the other logic is executed. However, it needs to be wrapped in a self-invoking async function.
1
1