Fundamentals 12 min read

Why Python and JavaScript Coroutines Evolved in Parallel: A Comparative Guide

This article compares the evolution of coroutines in Python and JavaScript, explaining their shared goals, core concepts, historical milestones, mature implementations, and practical code examples to help newcomers understand asynchronous programming across both languages.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Why Python and JavaScript Coroutines Evolved in Parallel: A Comparative Guide

Introduction

Having little exposure to front‑end development, the author discovered that the history of asynchronous programming in Python and JavaScript is strikingly similar.

Common Goals

Multi‑core CPUs require concurrency despite the single‑threaded origins of many languages.

Simplify code and avoid callback hell by providing keyword support.

Coroutines use fewer resources than threads and switch contexts faster.

What Is a Coroutine?

A coroutine is a function that can be paused at a pause point , resumed later while preserving its arguments and local variables, and relies on an event loop as the foundation of asynchronous programming.

Chaotic History

Python Coroutine Evolution

Python 2.2 introduced generators.

Python 2.5 added the yield keyword.

Python 3.4 brought yield from and the experimental asyncio I/O framework (PEP 3156).

Python 3.5 introduced async / await syntax (PEP 492).

Python 3.6 formalized the asyncio library.

Other coroutine implementations such as Gevent also appeared during this period.

def foo():
    print("foo start")
    a = yield 1
    print("foo a", a)
    yield 2
    yield 3
    print("foo end")

gen = foo()
print(next(gen))
print(gen.send("a"))
print(next(gen))
print(next(foo()))
print(next(foo()))
list(foo())
"""
foo start
1
foo a a
2
3
foo start
1
foo start
1
foo start
foo a None
foo end
"""

JavaScript Coroutine Evolution

Synchronous code.

Callback hell in early asynchronous JavaScript.

ES6 introduced Promises, generators (with function* foo(){}) and the yield keyword.

ES7 added async / await, which wraps a generator and returns a Promise.

Promises also use callbacks via .then() and .catch(), turning nested callbacks into a chain of .then() calls for clearer code.

Generators are implemented on top of coroutines.

function* foo() {
    console.log("foo start");
    a = yield 1;
    console.log("foo a", a);
    yield 2;
    yield 3;
    console.log("foo end");
}

const gen = foo();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3

Python Coroutine Maturity

Awaitable objects include coroutines, tasks, and Future objects.

Coroutines

Defined with async def.

Calling a coroutine function returns a coroutine object.

Older style coroutines are based on generators.

Tasks

Created with asyncio.create_task() to schedule coroutines.

Tasks run in the event loop and pause when awaiting a Future.

The event loop executes one task at a time, switching to other tasks when a Future is pending.

Future Objects

Bridge low‑level callback code with high‑level async/await code.

When a Future completes, its registered callbacks are invoked, resuming the awaiting coroutine.

Event Loop Implementations

libevent/libev (used by Gevent).

Tornado’s own IOLoop.

picoev (used by meinheld).

uvloop (a high‑performance loop built on libuv, used by Sanic).

Example

import asyncio, time

async def exec():
    await asyncio.sleep(2)
    print('exec')

async def go():
    print(time.time())
    await asyncio.gather(exec(), exec())
    print(time.time())

if __name__ == '__main__':
    asyncio.run(go())

JavaScript Coroutine Maturity

Promise Basics

A Promise is a state machine with three states: pending, fulfilled, and rejected.

async/await Sugar

async

/ await wrap generators and promises, making asynchronous code look synchronous and improving error handling, branching, and debugging.

JavaScript Event Loop Mechanics

All tasks run on the main thread forming an execution stack.

A task queue holds events once asynchronous operations produce results.

When the stack is empty, the engine processes the task queue.

Micro‑tasks (e.g., Promise callbacks) are processed before macro‑tasks (e.g., setTimeout, I/O) in each loop iteration.

Example

var sleep = function(time) {
    console.log("sleep start");
    return new Promise(function(resolve, reject) {
        setTimeout(function(){ resolve(); }, time);
    });
};

async function exec() {
    await sleep(2000);
    console.log("sleep end");
}

async function go() {
    console.log(Date.now());
    const c1 = exec();
    console.log("-------1");
    const c2 = exec();
    console.log(c1, c2);
    await c1;
    console.log("-------2");
    await c2;
    console.log(c1, c2);
    console.log(Date.now());
}

go();

Summary and Comparison

Both languages now support async / await, use similar concepts (generators, futures/promises), and rely on an event loop, though the underlying implementations differ: Python’s asyncio offers extensive APIs and fine‑grained control, while JavaScript’s event loop is largely hidden in browsers and Node.js.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Asynccoroutineevent loopPromiseawait
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.