JavaScript has async/await because it solves a very specifically JavaScript problem: the language has no threads and all your code lives in the main event loop of the browser tab. If you do the normal thing of pausing your JavaScript until an I/O operation returns, the browser hangs. So you need to write everything with callbacks (continuation passing style), which is a pain in the ass and breaks exception handling. Promises were introduced to fix exceptions and async/await introduced to sugar over CPS.
There's also a very specifically Not JavaScript problem (that happens to also show up in Node.js): exotic concurrency scenarios involving lots of high-latency I/O (read: network sockets). OS kernel/CRT[0] threads are a lot more performant than they used to be but they still require bookkeeping that an application might not need and usually allocate a default stack size that's way too high. There's no language I know of where you can ask for the maximum stack size of a function[1] and then use that to allocate a stack. But if you structure your program as callbacks then you can share one stack allocation across multiple threads and heap-allocate everything that needs to live between yield points.
You can do exotic concurrency without exposing async to the language. For example, Go uses (or at least one point it did) its own thread management and variable-size stacks. This is more invasive to a program than adopting precise garbage collection and requires deep language support[3]. Yes, even moreso than async/await, which just requires the compiler transform imperative code into a state machine on an opt-in basis. You'd never, ever see, say, Rust implement transparent green threading[2].
To be clear, all UI code has to live in an event loop. Any code that lives in that event loop has to be async or the event loop stops servicing user input. But async code doesn't infect UI code in any other language because you can use threads and blocking executors[4] as boundaries between the sync and async worlds. The threading story in JavaScript doesn't exist, it has workers instead. And while workers use threads internally, the structured clone that is done to pass data between workers makes workers a lot more like processes than threads in terms of developer experience.
[0] Critical Runtime Theory: every system call is political
[1] ActionScript 3 had facilities for declaring a stack size limit but I don't think you could get that from the runtime.
async/await syntax in Rust also just so happens to generate an anonymous type whose size is the maximum memory usage of the function across yield points, since Rust promises also store the state of the async function when it's yielded. Yes, this also means recursive yields are forbidden, at least not without strategic use of `Box`. And it also does not cover sync stack usage while a function is being polled.
[2] I say this knowing full well that alpha Rust had transparent green threading.
[3] No, setjmp/longjmp does not count.
[4] i.e. when calling async promise code from sync blocking functions, just sleep the current thread or poll/spinwait until the promise resolves
There is an old strategy that is kind of the inverse of this this called Dogs of the Dow where. You buy with stocks with the highest dividend-to-price ratio (implicitly underperforming), looking for the rebound.
I've become a fan of unique, relatively short and "human-readable" IDs, such at the ones used by Stripe, e.g. `cus_MJA953cFzEuO1z` for an ID of a customer. Here's a Stripe dev article on the topic: https://dev.to/stripe/designing-apis-for-humans-object-ids-3...
If you use JavaScript/TypeScript, you can make them like this:
function makeSlug(length: number): string {
const validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const randomBytes = crypto.randomBytes(length);
let result = "";
for (let i = 0; i < length; i++) {
result += validChars[randomBytes[i] % validChars.length];
}
return result;
}
function makeId(tableName: string): string {
const idSpec = TABLE_NAME_TO_ID_SPEC[tableName];
const prefix = idSpec.prefix;
const slugLength = idSpec.length - prefix.length - 1;
return `${prefix}_${makeSlug(slugLength)}`;
}
One does not send Kurt Gödel to do this. He had to be coached during his citizenship test. “1947, he took the test to become a U.S. citizen, sponsored by Einstein and their mutual friend, the economist Oskar Morgenstern. When he appeared before the judge, after answering the first questions satisfactorily, he told the judge that he had analyzed the U.S. Constitution and that it had a drafting problem, which allowed the U.S. to legally become a dictatorship or a fascist state, as had happened in Austria. Gödel’s two friends were horrified because they saw that his citizenship was in jeopardy, and he could be deported to Europe. The judge himself stopped Gödel by uttering the pragmatic phrase “Oh God, let’s not get into this” and ending the examination before the logician could say anything more.” [1] https://english.elpais.com/science-tech/2023-07-01/kurt-gode...
Question: I have this person on my team who talks WAY too much and never notices it. They LOVE hearing themselves talk and never shut up. Should I tell them to get this app?
---
Answer: First off... I believe your struggle with this person is 100% real. I fully believe their behavior is affecting you negatively.
But, my answer is a STRONG NO. Please don’t use Unblah as a proxy for a difficult conversation that sounds like it needs to be had.
Think about it: They would never use it anyways, because, as you’re saying yourself “...and never even notice it.”.
They don't have a problem.
You do.
I don't know how much rapport you two have, how much safe space you can create for resolving this situation, etc.
So, to keep everyone safe, please check with HR or leadership on how to best deal with this situation if it impacts you, your team and your performance.
For learning more on this kind of topic, I can recommend “Difficult Conversations: How to Discuss What Matters Most” by Bruce Patton, Douglas Stone, and Sheila Heen.