Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Async IIFEs, Semicolons, and JS Pitfalls You Should Know

Keshav Kabra

Software Development

Can You Spot the Difference?

Take a look at these two JavaScript code snippets. They look nearly identical — but do they behave the same?

Snippet 1 (without semicolon):

CODE: https://gist.github.com/velotiotech/5e5a48b7a49a7fd379a17e72be13693f.js

Snippet 2 (with semicolon):

CODE: https://gist.github.com/velotiotech/e6effb614a01397e1338e8ed126d29bc.js

What Happens When You Run Them?

❌ Snippet 1 Output:

TypeError: (intermediate value) is not a function

✅ Snippet 2 Output:

logging result -> printing content of promise1

Why Does a Single Semicolon Make Such a Big Difference?

We’ve always heard that semicolons are optional in JavaScript. So why does omitting just one lead to a runtime error here?

Let's investigate.

What’s Really Going On?

The issue boils down to JavaScript’s Automatic Semicolon Insertion (ASI).

When you omit a semicolon, JavaScript tries to infer where it should end your statements. Usually, it does a decent job. But it's not perfect.

In the first snippet, JavaScript parses this like so:

const promise1 = new Promise(...)(async () => { ... })();

Here, it thinks you are calling the result of new Promise(...) as a function, which is not valid — hence the TypeError.

But Wait, Aren’t Semicolons Optional in JavaScript?

They are — until they’re not.

Here's the trap:

If a new line starts with:

  • (
  • [
  • + or -
  • / (as in regex)

JavaScript might interpret it as part of the previous expression.

That’s what’s happening here. The async IIFE starts with (, so JavaScript assumes it continues the previous line unless you forcefully break it with a semicolon.

🔍 Key Takeaways:

  • ASI is not foolproof and can lead to surprising bugs.
  • A semicolon before an IIFE ensures it is not misinterpreted as part of the preceding line.
  • This is especially important when using modern JavaScript features like async/await, arrow functions, and top-level code.

💡 Why You Should Use Semicolons Consistently

Even though many style guides (like those from Prettier or StandardJS) allow you to skip semicolons, using them consistently provides:

✅ Clarity

You eliminate ambiguity and make your code more readable and predictable.

✅ Fewer Bugs

You avoid hidden edge cases like this one, which are hard to debug — especially in production code.

✅ Compatibility

Not all environments handle ASI equally. Tools like Babel, TypeScript, or older browsers might behave differently.

🧠 Conclusion

The difference between working and broken code here is one semicolon. JavaScript's ASI mechanism is helpful, but it can fail — especially when lines begin with characters like ( or [.

If you're writing clean, modular, modern JavaScript, consider adding that semicolon. It’s a tiny keystroke that saves a lot of headaches.

Happy coding — and remember, when in doubt, punctuate!

Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

Async IIFEs, Semicolons, and JS Pitfalls You Should Know

Can You Spot the Difference?

Take a look at these two JavaScript code snippets. They look nearly identical — but do they behave the same?

Snippet 1 (without semicolon):

CODE: https://gist.github.com/velotiotech/5e5a48b7a49a7fd379a17e72be13693f.js

Snippet 2 (with semicolon):

CODE: https://gist.github.com/velotiotech/e6effb614a01397e1338e8ed126d29bc.js

What Happens When You Run Them?

❌ Snippet 1 Output:

TypeError: (intermediate value) is not a function

✅ Snippet 2 Output:

logging result -> printing content of promise1

Why Does a Single Semicolon Make Such a Big Difference?

We’ve always heard that semicolons are optional in JavaScript. So why does omitting just one lead to a runtime error here?

Let's investigate.

What’s Really Going On?

The issue boils down to JavaScript’s Automatic Semicolon Insertion (ASI).

When you omit a semicolon, JavaScript tries to infer where it should end your statements. Usually, it does a decent job. But it's not perfect.

In the first snippet, JavaScript parses this like so:

const promise1 = new Promise(...)(async () => { ... })();

Here, it thinks you are calling the result of new Promise(...) as a function, which is not valid — hence the TypeError.

But Wait, Aren’t Semicolons Optional in JavaScript?

They are — until they’re not.

Here's the trap:

If a new line starts with:

  • (
  • [
  • + or -
  • / (as in regex)

JavaScript might interpret it as part of the previous expression.

That’s what’s happening here. The async IIFE starts with (, so JavaScript assumes it continues the previous line unless you forcefully break it with a semicolon.

🔍 Key Takeaways:

  • ASI is not foolproof and can lead to surprising bugs.
  • A semicolon before an IIFE ensures it is not misinterpreted as part of the preceding line.
  • This is especially important when using modern JavaScript features like async/await, arrow functions, and top-level code.

💡 Why You Should Use Semicolons Consistently

Even though many style guides (like those from Prettier or StandardJS) allow you to skip semicolons, using them consistently provides:

✅ Clarity

You eliminate ambiguity and make your code more readable and predictable.

✅ Fewer Bugs

You avoid hidden edge cases like this one, which are hard to debug — especially in production code.

✅ Compatibility

Not all environments handle ASI equally. Tools like Babel, TypeScript, or older browsers might behave differently.

🧠 Conclusion

The difference between working and broken code here is one semicolon. JavaScript's ASI mechanism is helpful, but it can fail — especially when lines begin with characters like ( or [.

If you're writing clean, modular, modern JavaScript, consider adding that semicolon. It’s a tiny keystroke that saves a lot of headaches.

Happy coding — and remember, when in doubt, punctuate!

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings