Cool video about the journey/history of how Rust implements asynchronous non-blocking code!

Starts off with terms & their definitions.

Talks about how Rust is a system programming language, and it HAS to be lightweight, but adding an async runtime into the language adds an additional overhead.

In the beginning, Rust used green threads as opposed to native threads. But it does not make sense for a systems programming language, so it was eventually separated into libgreen. People also wanted to build network systems in Rust, and version 1.0 was looming, so they had to decide.

JS introduced the concept of event loop and promises. It had a messy nested callback issue, so they added promise chaining, before eventually adding an await syntax, which is an asynchronous keyword that looks synchronous.

// Callback: Pass function. It gets called when done
get((result) => process(result));
 
// Promise: get() returns a promise, you chain .then()
const promise = get()
promise.then((result) => process(result));
 
// Async/await: syntactic sugar over promises
const result = await get();
process(result);

Scala introduced the concept of Futures. Scala is also a statically typed language like Rust, so it is more compatible. So Rust added a Future trait with Future::poll for the community to develop a runtime crate with (tokio for example).

The community also argued extensively about the await syntax. One of the main reasons is due to the ? operator:

await future;
 
// with `?` operator:
await future?;
await (future?);
(await future)?;
?await future;
 
// especially with nested awaits:
(await (await future)?)?

Rust eventually decided on these. It is uniquely used in Rust

let fut = get();
get.await?;
 
// nested
get.await?.await?;

Some people viscerally hated it. Many people disliked it, but favored it after few minutes of using it.