Last modified: September 13, 2025
This article is written in: πΊπΈ
Asynchronous programming is a technique used to achieve concurrency, where tasks can be executed independently without waiting for other tasks to finish. It allows for nonblocking behavior, in contrast to synchronous execution that waits for one task to complete before starting the next task.
Asynchronous programming is particularly useful for tasks that involve I/O operations, such as fetching data from a database, where waiting for the data retrieval could freeze the user interface.
Asynchronous programming offers non-blocking execution, which is especially beneficial for I/O-bound operations. The two main pillars of this paradigm are the event loop and async functions.
yield
or await
, depending on the programming language.
Function: Coroutine:
+-------------------+ +-------------------+
| Start | | Start |
+-------------------+ +-------------------+
| |
v v
+-------------------+ +-------------------+
| Execute Task | | Execute Part 1 |
+-------------------+ +-------------------+
| |
v v
+-------------------+ +-------------------+
| End | | Pause |
+-------------------+ +-------------------+
|
v
+-------------------+
| Execute Part 2 |
+-------------------+
|
v
+-------------------+
| End |
+-------------------+
βββββββββββββββ
β Code Runs β
β on Stack β
βββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββ
β Async Functions / Web APIs β
β do background tasks, timers, β
β network calls, etc. β
βββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββ (Completion triggers callback)
β Callback β β placed into Task Queue
βββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββ
β Task Queue β
β (events, callbacks waiting) β
βββββββββββββββββββββββββββββββββ
β
(Event Loop Checks)
βΌ
βββββββββββββββ
β Call Stack β ββ Pushed again
βββββββββββββββ
β
βββββββΊ [ Repeat Cycle... ]
await
or callbacks, which works well for I/O-bound concurrency, while omitting this model forces developers to block on slow operations; for example, async HTTP requests let hundreds of downloads proceed concurrently without dedicated threads.Async gives you concurrency on one thread by not blocking; threads give you preemptive concurrency and, with multiple cores, true parallelism.
Legend: letters = task running on CPU; -
= not running (blocked, waiting, or preempted)
I. Synchronous, single thread
single thread: AAAA BBBBBBBBBBBBBBBBBBBBBB CCCCCCCCCC
Tasks run to completion one after another; others wait.
II. Synchronous, multiple threads (OS preemption)
thread 1: AAAAAAAAAAAA------------------------------
thread 2: ------------BBBBBB------------------------
thread 3: ------------------CCCCCCCCCCCCCCCCCCCCCCCC
Each thread can be scheduled independently; with multiple cores, B and C may truly run in parallel.
III. Asynchronous, single thread (cooperative)
single thread: AAAA----BBBB----AA--CCC--AA--BBBB----CCCC
Tasks yield at awaits; the event loop runs whatever is ready. No parallel CPU workβjust efficient interleaving during I/O waits.
IV. Asynchronous + multiple threads (hybrid)
thread 1 (event loop): AAAAAA--A--A--C--A--B--C--A------
thread 2 (worker): ---BBBBBBBB-----------------------
thread 3 (worker): -----------CCCCCCCC--------------
An async event loop offloads blocking/CPU-heavy bits to a thread (or process) pool.
Quick comparison
Aspect | Asynchrony | Threads |
Scheduling | Cooperative (await /callbacks) |
Preemptive (OS time slices) |
Best for | Many I/O-bound tasks (network, disk) | CPU-bound work; true parallelism |
Cost | Lightweight (no per-task stack) | Heavier (stack, context switches) |
Hazards | Blocking the loop stalls everything | Races, deadlocks, contention |
Composition | Futures/Promises, event loop | Locks, atomics, queues, thread-safe libs |
When to use what
Practical tips
run_in_executor
maintain system efficiency, whereas failing to do so can lead to bottlenecks; an example is offloading CPU-heavy image processing to a separate thread.asyncio.debug()
reveal task states and pauses, aiding problem resolution, whereas relying only on traditional debugging tools leaves gaps; real-world debugging of web crawlers often relies on such logging.
| Use case | Pattern summary | C++ (preferred) | Python (preferred) | Why this choice | Shutdown behavior |
|---|---|---|---|---|---|
| High-concurrency HTTP **client** (scraper/crawler) | Fire thousands of non-blocking requests with bounded concurrency | C++20 coroutines + Boost.Asio/Beast; semaphore to cap in-flight | asyncio
+ aiohttp
+ asyncio.Semaphore
| Excellent overlap of network waits; minimal threads | Cancel pending tasks, close ClientSession
, await gather(return_exceptions=True)
|
| High-concurrency HTTP **server** (API) | Event-loop reactor accepts and services requests | Boost.Asio/Beast coroutines; strand for handler serialization | FastAPI/Starlette on uvicorn
/hypercorn
(async) | Scales with connections, low memory/ctx switches | Stop accepting, drain keep-alives, graceful shutdown hook, time-boxed cancel of tasks |
| WebSockets chat/broadcast | Long-lived duplex connections, fan-out messages | Asio coroutines + Beast websockets | websockets
/ aiohttp
WS | Async fits many idle sockets efficiently | Close WS with codes, cancel producers, flush queues |
| Reverse proxy / gateway | Stream request/response bodies, back-pressure | Asio coroutines + Beast, async stream copy | aiohttp
proxy / anyio
streams | Zero-copy-ish streaming, flow control | Cancel copy tasks, half-close, drain, then close |
| Streaming pipeline (socketβtransformβsink) | Staged coroutines linked by queues | Asio + coroutines + bounded queues | asyncio.Queue
+ tasks per stage | Back-pressure & simple composition | Send sentinels/cancel, drain queues, await tasks |
| DB access (async driver) | Pooled async connections, transactions | Driver-specific async APIs (e.g., ozo
for PG) | asyncpg
/ databases
/ SQLAlchemy async | Avoid thread pools for I/O; better throughput | Close pools, finish in-flight txns, cancel long queries |
| Periodic jobs/heartbeats | while
loop with async sleep and cancellation | co_await async_timer
(Asio steady_timer) | asyncio.TaskGroup
+ asyncio.sleep()
| Cheap timers; easy cooperative cancel | Respect cancel, final iteration optional, stop timers |
| RPC client with retries/timeouts | Issue calls with per-call timeout, jittered retry | Asio + timers + coroutines | asyncio.wait_for
+ retry (tenacity/hand-rolled) | Compose timeouts & retries declaratively | Cancel on shutdown, abort retries, close transports |
| Bulk cloud uploads/downloads | Many concurrent objects with windowing | Asio coroutines + HTTP/S3 libs | aiohttp
/SDK async clients | Hide latency; cap bandwidth with semaphores | Finish in-flight or checkpoint parts; close sessions |
| Batched DNS resolution | Pipeline many lookups concurrently | Asio async resolver + coroutines | asyncio.getaddrinfo
in threadpool or aiodns
| Parallelize high-latency lookups | Cancel outstanding; cache results; close resolver |
| MQ consumers/producers | Async consume/ack/publish with flow control | Asio + AMQP/Kafka client coroutines | aio-pika
, aiokafka
| Natural fit for broker I/O | Stop consume, flush acks/publishes, close channels |
| GUI app non-blocking network I/O | Keep UI thread responsive | Qt + coroutines/Asio; integrate event loops | Qt + qasync
+ asyncio
| Avoids UI stalls; fewer threads | Cancel tasks before closing UI; disconnect signals |
| IoT gateway (many devices) | Thousands of idle TCP/MQTT sessions | Asio coroutines + strands | asyncio-mqtt
/ asyncio
sockets | Async handles massive concurrency cheaply | Unsubscribe, close sockets, persist offsets/state |
| Rate-limited API worker | Token bucket + bounded concurrency | Asio timers + custom bucket | anyio
/asyncio
+ leaky/token bucket | Smooths bursts; avoids 429s | Flush queue, stop token refills, cancel waiters |
| Async fileβsocket streaming | Non-blocking file read/write to sockets | io_uring
/ Asio + files (platform-dep.) | aiofiles
+ asyncio
streams | Preserve event-loop responsiveness | Flush buffers, fsync if needed, close handles |
| Bulk email/SMS send | Many slow servers; pipeline SMTP/API calls | Asio + SMTP/HTTP libs | aiosmtplib
/ async provider SDKs | Great for I/O-bound fan-out | Drain queues, handle deferred failures, close clients |
| Health checks/monitoring fan-out | Probe many endpoints on schedule | Asio coroutines + timers | asyncio
+ aiohttp
+ gather
| Concurrency with small footprint | Cancel probes on exit; aggregate partial results |
| Lightweight multiplayer/session server | Many small messages per client | Asio UDP/TCP coroutines | asyncio
UDP/TCP protocols | Low latency, single-threaded logic | Kick clients, flush outbound, close transports |
| Metrics fan-in (statsd/OTLP) | Receive, batch, forward asynchronously | Asio + UDP/TCP, batch timers | asyncio
datagrams + batch send | High throughput with batching | Flush batch, stop intake, close sockets |
| Async subprocess orchestration | Start many short jobs, stream stdio | Asio + Boost.Process + async pipes | asyncio.create_subprocess_exec
| Avoid blocking; supervise easily | Terminate on timeout, drain pipes, await wait()
|
| Webhook/event handler workers | Handle many webhooks concurrently | Asio HTTP server + task queue | FastAPI + background TaskGroup
| Bursty, I/O-bound workloads | Stop intake, finish tasks (time-boxed), persist offsets |
| βFire-and-forgetβ background task | Task not waited but tracked | Coroutine + supervisor registry | asyncio.create_task
+ tracking | Keep app responsive, but retain control | Store task refs; cancel explicitly on shutdown |
| Bridging blocking call into async | Isolate blocking library call | Thread pool just for the call | asyncio.to_thread()
| Keep loop unblocked without full rewrite | Await completion; cap worker threads; cancel if long |
Asynchronous programming in C++ involves performing tasks without blocking the main thread, allowing other operations to continue in parallel. This can be particularly useful for I/O-bound or computationally intensive tasks. The C++ Standard Library provides facilities for asynchronous programming, including the std::async
function, std::future
, and std::promise
.
std::async
The std::async
function runs a function asynchronously, returning a std::future
that will eventually hold the result of the function.
#include <iostream>
#include <future>
#include <thread>
int compute(int x) {
std::this_thread::sleep_for(std::chrono::seconds(2)); // Simulate a long computation
return x * x;
}
int main() {
std::future<int> future = std::async(std::launch::async, compute, 5);
std::cout << "Doing other work while waiting for the result..." << std::endl;
int result = future.get(); // Wait for the result
std::cout << "Result: " << result << std::endl;
return 0;
}
In this example, std::async
launches the compute
function asynchronously, allowing the main thread to continue executing other code. The future.get()
method waits for the result and retrieves it once the computation is complete.
std::future
and std::promise
std::future
and std::promise
provide a way to communicate between threads asynchronously. A std::promise
object is used to set a value that will be available to a std::future
object.
#include <iostream>
#include <future>
#include <thread>
void set_value(std::promise<int>& promise) {
std::this_thread::sleep_for(std::chrono::seconds(1));
promise.set_value(10); // Set the value to be retrieved by future
}
int main() {
std::promise<int> promise;
std::future<int> future = promise.get_future();
std::thread t(set_value, std::ref(promise));
std::cout << "Waiting for value..." << std::endl;
int value = future.get(); // Wait for the value
std::cout << "Value: " << value << std::endl;
t.join();
return 0;
}
In this example, the set_value
function sets a value to the promise, which is then retrieved by the future in the main thread.
std::future
The std::future
object provides a way to wait for a result that is being computed asynchronously.
#include <iostream>
#include <future>
#include <thread>
int slow_add(int a, int b) {
std::this_thread::sleep_for(std::chrono::seconds(3));
return a + b;
}
int main() {
std::future<int> future = std::async(std::launch::async, slow_add, 3, 4);
while (future.wait_for(std::chrono::milliseconds(500)) != std::future_status::ready) {
std::cout << "Waiting for the result..." << std::endl;
}
std::cout << "Result: " << future.get() << std::endl;
return 0;
}
Here, future.wait_for
periodically checks if the result is ready, allowing the main thread to perform other tasks while waiting.
Exceptions thrown in asynchronous tasks are captured by std::future
and can be re-thrown when future.get()
is called.
#include <iostream>
#include <future>
#include <stdexcept>
int risky_task() {
throw std::runtime_error("Something went wrong");
return 42; // This line won't be reached
}
int main() {
std::future<int> future = std::async(std::launch::async, risky_task);
try {
int result = future.get();
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
return 0;
}
In this code, the exception thrown in risky_task
is caught in the main thread when future.get()
is called.
std::shared_future
A std::shared_future
allows multiple threads to share the result of an asynchronous operation.
#include <iostream>
#include <future>
#include <thread>
#include <vector>
int compute_value() {
std::this_thread::sleep_for(std::chrono::seconds(2));
return 10;
}
int main() {
std::shared_future<int> shared_future = std::async(std::launch::async, compute_value).share();
std::vector<std::thread> threads;
for (int i = 0; i < 5; ++i) {
threads.emplace_back([shared_future, i]() {
std::cout << "Thread " << i << ": " << shared_future.get() << std::endl;
});
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}
In this example, the result of compute_value
is shared among multiple threads using std::shared_future
.
std::future
Asynchronous continuations allow chaining of asynchronous operations.
#include <iostream>
#include <future>
#include <chrono>
int initial_task() {
std::this_thread::sleep_for(std::chrono::seconds(2));
return 5;
}
int next_task(int input) {
return input * 2;
}
int main() {
auto future = std::async(std::launch::async, initial_task)
.then([](std::future<int> fut) {
return next_task(fut.get());
});
std::cout << "Result: " << future.get() << std::endl;
return 0;
}
Here, initial_task
runs asynchronously, and once it completes, next_task
is executed with the result.
std::async
, std::future
, and std::promise
for cleaner and more efficient asynchronous programming.
No. | Filename | Description |
1 | 01_basic_async.cpp | Create and start a basic asynchronous task |
2 | 02_future_create_task.cpp | Create a task using Future and run it asynchronously |
3 | 03_future_read_result.cpp | Read the result of a completed Future task |
4 | 04_pause_resume.cpp | Pause and resume asynchronous tasks |
5 | 05_run_heavy_functions.cpp | Execute heavy functions asynchronously |
6 | 06_data_sharing_queue.cpp | Share data between asynchronous tasks using a Queue |
7 | 07_semaphore.cpp | Control access to shared resources with a Semaphore |
8 | 08_producer_consumer.cpp | Implement a producer-consumer pattern asynchronously |
9 | 09_fetch_parallel.cpp | Fetch data in parallel using async tasks |
10 | 10_mutex.cpp | Use a Mutex to synchronize access to shared resources |
11 | 11_barrier.cpp | Synchronize multiple asynchronous tasks using a Barrier |
12 | 12_async_generator.cpp | Create and use asynchronous generators |
13 | 13_async_server.cpp | Implement an asynchronous server |
14 | 14_distributed_computing.cpp | Demonstrate distributed computing with async tasks |
In Python, asynchronous programming allows you to run code concurrently without creating new threads or processes. This is especially useful for I/O-bound tasks, such as network requests or file operations, where waiting for an operation to complete would otherwise block other code from running. Python's asyncio
library provides the primary framework for writing asynchronous code using the async
and await
keywords.
An asynchronous function is defined using the async def
syntax. These functions return a coroutine, which is an object representing the eventual result of the function.
import asyncio
async def print_message(message):
print(message)
# Example usage
async def main():
await print_message("Hello from an asynchronous function!")
asyncio.run(main())
In this example, print_message
is an asynchronous function that prints a message. The main
function calls it with await
, indicating it will wait for the coroutine to complete.
You can run multiple asynchronous tasks concurrently using asyncio.create_task()
or by awaiting multiple coroutines.
import asyncio
async def print_message(message):
await asyncio.sleep(1)
print(message)
async def main():
task1 = asyncio.create_task(print_message("Task 1"))
task2 = asyncio.create_task(print_message("Task 2"))
await task1
await task2
asyncio.run(main())
Here, asyncio.create_task()
schedules the coroutines to run concurrently. The await
statements ensure that main
waits for both tasks to finish.
Asynchronous functions are ideal for I/O-bound tasks where blocking operations can slow down the program. For example, making HTTP requests.
import asyncio
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
url = "http://example.com"
html = await fetch(url)
print(html)
asyncio.run(main())
In this example, fetch
uses aiohttp
for asynchronous HTTP requests. This allows multiple requests to be handled without blocking the event loop.
You can run multiple coroutines concurrently using await asyncio.gather()
.
import asyncio
async def fetch_data(n):
await asyncio.sleep(n)
return f"Data {n}"
async def main():
results = await asyncio.gather(
fetch_data(1),
fetch_data(2),
fetch_data(3)
)
print(results)
asyncio.run(main())
asyncio.gather()
waits for all the provided coroutines to finish and returns their results in a list.
Async context managers, defined with async with
, are used to manage resources that require cleanup after use.
import asyncio
import aiofiles
async def write_to_file(filename, content):
async with aiofiles.open(filename, 'w') as file:
await file.write(content)
async def main():
await write_to_file('example.txt', 'Hello, Async World!')
asyncio.run(main())
In this example, aiofiles
is used for asynchronous file operations. The file is automatically closed after writing.
Handling exceptions in asynchronous code is similar to synchronous code, using try-except blocks.
import asyncio
async def may_raise_exception():
await asyncio.sleep(1)
raise ValueError("An error occurred!")
async def main():
try:
await may_raise_exception()
except ValueError as e:
print(f"Caught an exception: {e}")
asyncio.run(main())
Here, the exception raised in may_raise_exception
is caught and handled in main
.
Asynchronous iterators and iterables allow for asynchronous looping, useful when dealing with streams or large datasets.
import asyncio
class AsyncCounter:
def __init__(self, limit):
self.limit = limit
self.count = 0
async def __aiter__(self):
return self
async def __anext__(self):
if self.count < self.limit:
await asyncio.sleep(1)
self.count += 1
return self.count
else:
raise StopAsyncIteration
async def main():
async for number in AsyncCounter(3):
print(number)
asyncio.run(main())
In this example, AsyncCounter
is an asynchronous iterable that generates numbers with a delay.
try...finally
blocks to clean up resources if a task is canceled.
No. | Filename | Description |
1 | 01_basic_async.py | Create and start a basic asynchronous task |
2 | 02_future_create_task.py | Create a task using Future and run it asynchronously |
3 | 03_future_read_result.py | Read the result of a completed Future task |
4 | 04_pause_resume.py | Pause and resume asynchronous tasks |
5 | 05_run_heavy_functions.py | Execute heavy functions asynchronously |
6 | 06_data_sharing_queue.py | Share data between asynchronous tasks using a Queue |
7 | 07_semaphore.py | Control access to shared resources with a Semaphore |
8 | 08_producer_consumer.py | Implement a producer-consumer pattern asynchronously |
9 | 09_fetch_parallel.py | Fetch data in parallel using async tasks |
10 | 10_mutex.py | Use a Mutex to synchronize access to shared resources |
11 | 11_barrier.py | Synchronize multiple asynchronous tasks using a Barrier |
12 | 12_async_generator.py | Create and use asynchronous generators |
13 | 13_async_server.py | Implement an asynchronous server |
14 | 14_distributed_computing.py | Demonstrate distributed computing with async tasks |
Node.js is inherently designed for asynchronous programming, primarily due to its non-blocking I/O model. It uses an event-driven architecture, which allows for efficient handling of concurrent operations. Asynchronous code in Node.js can be written using callbacks, Promises, and the async
/await
syntax.
Callbacks are the traditional way of handling asynchronous operations in Node.js. A callback is a function passed as an argument to another function, which will be called once the operation is complete.
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File contents:', data);
});
console.log('Reading file...');
In this example, fs.readFile
reads a file asynchronously and calls the provided callback function when the operation completes, either with an error or the file's data.
Promises provide a more elegant way to handle asynchronous operations by avoiding the callback pyramid of doom (nested callbacks). A Promise represents a value that may be available now, or in the future, or never.
const fs = require('fs').promises;
fs.readFile('example.txt', 'utf8')
.then(data => {
console.log('File contents:', data);
})
.catch(err => {
console.error('Error reading file:', err);
});
console.log('Reading file...');
Here, fs.promises.readFile
returns a Promise. The then
method handles the resolved value, while catch
handles any errors.
async
/await
The async
/await
syntax in Node.js (available from ECMAScript 2017) is syntactic sugar over Promises, making asynchronous code look and behave more like synchronous code.
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('example.txt', 'utf8');
console.log('File contents:', data);
} catch (err) {
console.error('Error reading file:', err);
}
}
readFile();
console.log('Reading file...');
In this example, async
declares an asynchronous function, and await
pauses the execution until the Promise is resolved, making the code more readable and maintainable.
Node.js provides several methods to handle multiple asynchronous operations concurrently, such as Promise.all
, Promise.race
, Promise.allSettled
, and Promise.any
.
const fetch = require('node-fetch');
async function fetchData() {
try {
const [response1, response2] = await Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2')
]);
const data1 = await response1.json();
const data2 = await response2.json();
console.log('Data 1:', data1);
console.log('Data 2:', data2);
} catch (err) {
console.error('Error fetching data:', err);
}
}
fetchData();
In this example, Promise.all
waits for all the promises to resolve before continuing. This is useful when you need to perform multiple independent asynchronous operations and handle their results together.
Proper error handling is crucial in asynchronous programming to avoid crashes and ensure reliability.
async function getData() {
try {
let response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(HTTP error! status: ${response.status}
);
}
let data = await response.json();
return data;
} catch (err) {
console.error('Error:', err.message);
// Additional error handling logic
}
}
getData();
In this example, the error is caught using a try-catch block, allowing for graceful handling of potential failures.
for-await-of
Node.js supports asynchronous iteration using for-await-of
, which is useful for processing streams of data.
const fs = require('fs');
const readline = require('readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('example.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
for await (const line of rl) {
console.log(Line from file: ${line}
);
}
}
processLineByLine();
Here, for-await-of
iterates over each line of a file asynchronously, making it easier to work with data that comes in pieces, like streams.
To avoid deeply nested callbacks (callback hell), use Promises or the async
/await
syntax. For example:
// Callback Hell Example
function doSomething(callback) {
fs.readFile('file1.txt', 'utf8', (err, data1) => {
if (err) return callback(err);
fs.readFile('file2.txt', 'utf8', (err, data2) => {
if (err) return callback(err);
callback(null, data1 + data2);
});
});
}
// Using Promises or async/await
async function doSomethingBetter() {
try {
const data1 = await fs.readFile('file1.txt', 'utf8');
const data2 = await fs.readFile('file2.txt', 'utf8');
return data1 + data2;
} catch (err) {
console.error('Error:', err);
}
}
Using Promises or async
/await
leads to cleaner and more maintainable code compared to deeply nested callbacks.
async_hooks
, Node.js inspector
, and unit testing to debug and test asynchronous code effectively.
No. | Filename | Description |
1 | 01_basic_async.js | Create and start a basic asynchronous task |
2 | 02_future_create_task.js | Create a task using Future and run it asynchronously |
3 | 03_future_read_result.js | Read the result of a completed Future task |
4 | 04_pause_resume.js | Pause and resume asynchronous tasks |
5 | 05_run_heavy_functions.js | Execute heavy functions asynchronously |
6 | 06_data_sharing_queue.js | Share data between asynchronous tasks using a Queue |
7 | 07_semaphore.js | Control access to shared resources with a Semaphore |
8 | 08_producer_consumer.js | Implement a producer-consumer pattern asynchronously |
9 | 09_fetch_parallel.js | Fetch data in parallel using async tasks |
10 | 10_mutex.js | Use a Mutex to synchronize access to shared resources |
11 | 11_barrier.js | Synchronize multiple asynchronous tasks using a Barrier |
12 | 12_async_generator.js | Create and use asynchronous generators |
13 | 13_async_server.js | Implement an asynchronous server |
14 | 14_distributed_computing.js | Demonstrate distributed computing with async tasks |
Here is a table comparing asynchronous programming features in C++, Python, and Node.js:
Concept | C++ | Python | Node.js |
Library | Standard Library (std::future , std::promise , std::async ) Boost.Asio |
asyncio |
Native support (callbacks, Promises) |
Event Loop | Depends on the library (e.g., Boost.Asio provides I/O context) | asyncio event loop |
Event loop provided by the libuv library |
Coroutine | C++20 coroutines (co_await , co_yield ) |
async def (coroutine functions) |
Async functions (async keyword) |
Future | std::future (contains the result of an asynchronous operation) |
asyncio.Future (contains the result of a coroutine) |
Promise (represents the eventual result of an async operation) |
Await | co_await (C++20) |
await (used inside async def ) |
await (used inside async functions) |
Async Call | std::async or custom implementation with Boost.Asio |
asyncio.create_task() , asyncio.gather() , etc. |
Callbacks, Promises, or async/await syntax |
Task | std::packaged_task (wraps a callable target) |
asyncio.Task (wraps a coroutine) |
Promises, async functions, or callbacks |