Here’s a code sample from a project I am working on.

Positional Promise.all
const readAsset = (relativePath: string) =>
  readFile(join(options.assetRoot, relativePath), "utf8");

const [
  registry,
  launcherHtml,
  launcherScript,
  launcherStyles,
  workspaceHtml,
  workspaceScript,
] = await Promise.all([
  loadWorkspaceRegistry(options.registryPath),
  readAsset("index.html"),
  readAsset("assets/launcher.js"),
  readAsset("assets/launcher.css"),
  readAsset("workspace.html"),
  readAsset("assets/workspace.js"),
]);

AFAIK this is the bog standard approach to awaiting a bunch of things at the same time. When its two to three items this is relatively ergonomic, but once you get past 5 I think it really just looks kind of gross.

All i want is a bunch of things to run at the same time, and the name of the thing is right next to the thing!

Because none of my problems or ideas are original, there is certainly many many approaches to obviate this “define over under instead of side by side” friction.

Here’s a sketch of what I thought would look the best.

Nested named wait groups
const loaded = await resolveProperties({
  registry: loadWorkspaceRegistry(options.registryPath),
  launcher: resolveProperties({
    html: readAsset("index.html"),
    script: readAsset("assets/launcher.js"),
    styles: readAsset("assets/launcher.css"),
  }),
  workspace: resolveProperties({
    html: readAsset("workspace.html"),
    script: readAsset("assets/workspace.js"),
  }),
});

loaded.registry;
loaded.launcher.html;
loaded.workspace.script;

The benefit is that you can next your calls into groups if you wanted to. Yes, I am aware this is a materially different execution pattern, it’s just an option!

So it’s kind of like a structured concurrency nursery, except you don’t get promises cancelled when siblings fail.

The helper is small:

resolveProperties
async function resolveProperties<
  const T extends Record<string, unknown>,
>(properties: T): Promise<{ [K in keyof T]: Awaited<T[K]> }> {
  const entries = await Promise.all(
    Object.entries(properties).map(async ([key, value]) => [
      key,
      await value,
    ] as const),
  );

  return Object.fromEntries(entries) as {
    [K in keyof T]: Awaited<T[K]>;
  };
}

I didn’t end up actually using this because I only had the one case of the longer-than-three promise chain in the repo. I’d rather stick to the gross conventions for a one-off, but it sure is pretty!