JavaScript Asynchronous APIs: The Misconception That Confused Me

작성자

카테고리:

← 피드로
DEV Community · Tejas Khanolkar · 2026-06-11 개발(SW)
Cover image for JavaScript Asynchronous APIs: The Misconception That Confused Me

Tejas Khanolkar

When I started learning JavaScript, I often heard things like:

  • setTimeout() is asynchronous.
  • fetch() is asynchronous.
  • addEventListener() is asynchronous.

After learning more deeply, I realized that this explanation is not completely accurate.

The real story is much more interesting.

The Question That Started It All

I was working with DOM methods like:

document.querySelector(".btn");
document.getElementById("title");

Enter fullscreen mode Exit fullscreen mode

These methods return elements immediately.

But then I noticed that methods like:

button.addEventListener("click", handler);

Enter fullscreen mode Exit fullscreen mode

use callbacks and seem asynchronous.

My question was:

If searching the DOM also takes time, why isn’t querySelector() asynchronous?

Understanding the Difference

The answer is simple:

JavaScript treats operations differently depending on whether the result is available immediately or not.

Case 1: Result Is Available Immediately

Example:

const btn = document.querySelector(".btn");

Enter fullscreen mode Exit fullscreen mode

The browser already has the DOM tree in memory.

Something like:

Document
 ├── body
 │    ├── div
 │    ├── button.btn
 │    └── p

Enter fullscreen mode Exit fullscreen mode

When JavaScript asks for .btn, the browser searches the existing DOM structure and returns the element immediately.

JavaScript
     ↓
Find element
     ↓
Return element
     ↓
Continue execution

Enter fullscreen mode Exit fullscreen mode

Because the result is available immediately, JavaScript waits for it.

This is called synchronous execution.

Case 2: Result Depends on the Future

Now consider:

button.addEventListener("click", () => {
  console.log("Clicked");
});

Enter fullscreen mode Exit fullscreen mode

Here JavaScript is not asking:

“Give me something right now.”

Instead it is saying:

“If a click happens in the future, run this function.”

The click may happen:

  • 1 second later
  • 5 minutes later
  • never

JavaScript cannot stop and wait forever.

So the browser stores the callback and lets JavaScript continue running.

The Biggest Realization

I learned something surprising:

addEventListener() itself is not asynchronous.

The function call is synchronous.

button.addEventListener("click", handler);

Enter fullscreen mode Exit fullscreen mode

What happens:

Register event
      ↓
Return immediately
      ↓
JavaScript continues

Enter fullscreen mode Exit fullscreen mode

Later:

User clicks
      ↓
Callback executes

Enter fullscreen mode Exit fullscreen mode

The callback execution is asynchronous.

The function call is not.

The Same Thing Happens With setTimeout

Consider:

console.log("1");

setTimeout(() => {
  console.log("2");
}, 1000);

console.log("3");

Enter fullscreen mode Exit fullscreen mode

Output:

1
3
2

Enter fullscreen mode Exit fullscreen mode

Many beginners think:

“setTimeout is asynchronous.”

More accurately:

setTimeout() call       → synchronous
Callback execution      → asynchronous

Enter fullscreen mode Exit fullscreen mode

What actually happens:

Run setTimeout()
      ↓
Register timer
      ↓
Return immediately
      ↓
Continue running code
      ↓
Timer finishes
      ↓
Execute callback

Enter fullscreen mode Exit fullscreen mode

What About fetch()?

console.log("Start");

fetch("/users");

console.log("End");

Enter fullscreen mode Exit fullscreen mode

Output:

Start
End

Enter fullscreen mode Exit fullscreen mode

Why?

Because fetch() does not wait for the server response.

Instead:

Start network request
      ↓
Return Promise immediately
      ↓
Continue execution
      ↓
Response arrives later

Enter fullscreen mode Exit fullscreen mode

Again:

Function call     → synchronous
Result delivery   → asynchronous

Enter fullscreen mode Exit fullscreen mode

The Mental Model That Finally Made Sense

Instead of asking:

“Is this function asynchronous?”

Ask:

“Can this function produce its result immediately?”

If yes:

document.querySelector();
document.getElementById();
Object.keys();
Array.map();

Enter fullscreen mode Exit fullscreen mode

These are synchronous.

If the result depends on a future event:

setTimeout();
fetch();
addEventListener();
WebSocket();

Enter fullscreen mode Exit fullscreen mode

Then JavaScript registers the work and continues.

The result arrives later.

The Rule I’ll Remember Forever

Most APIs that developers call “asynchronous functions” are actually:

Synchronous function calls
            +
Asynchronous result delivery

Enter fullscreen mode Exit fullscreen mode

Visualized:

Call Function
      ↓
Register Work
      ↓
Return Immediately
      ↓
JavaScript Continues
      ↓
Result Arrives Later
      ↓
Callback / Promise Runs

Enter fullscreen mode Exit fullscreen mode

Final Takeaway

The important distinction is not:

Synchronous Function
vs
Asynchronous Function

Enter fullscreen mode Exit fullscreen mode

The important distinction is:

Function Call
vs
When the Result Becomes Available

Enter fullscreen mode Exit fullscreen mode

Many JavaScript APIs execute synchronously when called, but their results become available asynchronously later.

Once I understood this, concepts like:

  • Event Listeners
  • Timers
  • Promises
  • Fetch API
  • Event Loop

became much easier to understand.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다