If you're coming from JavaScript, Python's asyncio can feel confusing.
I had the same question:
"Why do I need
asyncio? JavaScript never makes me import anything."
After understanding both, I realized the concepts are almost the same.
The biggest difference is who provides the event loop.
JavaScript
In JavaScript, the runtime (Browser or Node.js) already provides an event loop.
When you write:
async function getUsers() {
console.log("Before");
const response = await fetch("https://jsonplaceholder.typicode.com/users");
console.log("After");
}
getUsers();
What happens?
Before
(fetch request sent)
JavaScript Event Loop
↓
Runs other work while waiting
↓
API responds
↓
After
You never think about the event loop because it already exists.
The Browser (or Node.js) manages everything for you.
Python
Now let's write the same thing in Python.
import asyncio
import httpx
async def get_users():
print("Before")
response = await httpx.AsyncClient().get(
"https://jsonplaceholder.typicode.com/users"
)
print("After")
asyncio.run(get_users())
This looks very similar.
The difference is:
Instead of the Browser/Node.js providing the event loop automatically,
Python uses asyncio.
async function
↓
await
↓
asyncio Event Loop
↓
Network request
↓
Resume coroutine
The Biggest Difference
This is the one thing every JavaScript developer should remember.
JavaScript
Calling an async function starts it immediately.
async function hello() {
console.log("Hello");
}
hello();
Output:
Hello
Python
Calling an async function does NOT execute it.
async def hello():
print("Hello")
hello()
Output:
Nothing
RuntimeWarning:
coroutine 'hello' was never awaited
Why?
Because Python only creates a coroutine object.
To execute it, you need:
asyncio.run(hello())
or
await hello()
or
asyncio.create_task(hello())
await Works Almost the Same
JavaScript
async function signup() {
console.log("Start");
await fetch("/users");
console.log("Done");
}
Python
async def signup():
print("Start")
await httpx.AsyncClient().get("/users")
print("Done")
In both languages:
- The current function pauses.
- The event loop continues doing other work.
- When the API responds, execution resumes.
So if you already understand JavaScript's await, you already understand most of Python's await.
What Does asyncio.create_task() Mean?
Suppose sending an email takes 5 seconds.
You don't want your user to wait.
JavaScript
async function signup() {
await saveUser();
sendEmail(); // Don't await
return "User Created";
}
The email starts in the background while the response is returned immediately.
Python
async def signup():
await save_user()
asyncio.create_task(send_email())
return "User Created"
Exactly the same idea.
The difference is that Python explicitly asks the event loop to schedule the coroutine.
When Should You Use await?
If the next line depends on the result, use await.
user = await save_user()
Examples:
- Database queries
- API calls
- Reading files asynchronously
- Cache lookups
When Should You Use create_task()?
Use it only for background work.
Examples:
- Send email
- Push notification
- Analytics event
- Logging
- Cleanup jobs
asyncio.create_task(send_email())
Don't wait for it.
Continue immediately.
Don't Use Async for Everything
This is another common mistake.
Normal calculations don't need async.
def add(a, b):
return a + b
result = add(5, 10)
No await.
No asyncio.
No event loop.
Async is mainly useful for I/O-bound operations, such as:
- HTTP requests
- Database queries
- File I/O
- Redis
- WebSockets
JavaScript vs Python Cheat Sheet
| JavaScript | Python |
|---|---|
async function |
async def |
await fetch() |
await httpx.get() |
| Browser/Node.js Event Loop |
asyncio Event Loop |
setTimeout() |
asyncio.sleep() |
| Promise | Coroutine |
sendEmail() (don't await) |
asyncio.create_task(send_email()) |
Mental Model
If you're coming from JavaScript, remember this sentence:
JavaScript has a built-in event loop managed by the Browser or Node.js. Python exposes its event loop through the
asynciolibrary.
Everything else—async, await, pausing while waiting for I/O, and resuming execution—works very similarly.
Once I stopped thinking of asyncio as "something new" and instead saw it as Python's version of the JavaScript event loop, the whole concept became much easier to understand.
Top comments (0)