Destructuring with `await`

Ah, I was imagining the semantics would be more like this:

const {
  await a,
  await b
} = modules;

// is the same as

const a = await modules.a;
const b = await modules.b;

i.e. it awaits them all one at a time, in order, not using Promise.all() semantice. This means if both promises reject, we'll only ever see the error from the "a" promise, not the "b" one.

This isn't too different from how the reverse syntax works:

const modules = {
  a: await a,
  b: await b,
}

If it uses Promise.all() semantics, that would break my default expectation of how this works. Is Promise.all() semantics required for the use-cases you mentioned?

It would have to work that way - every await surfaces a rejection as an exception.

which way? the one I've proposed or the @theScottyJam amend?

As already mentioned at the beginning and later on:

This is for bootstrap performance reasons but if it's impossible to have then lets move on with one await after the other, after all if destructuring accessors throws one after the other and before the destructuring completes, it feels more aligned, it's bad for performance (when many await are destructured) but at least it would make @rdking concerns fade away (and the implementation easier to deal with and explain).

edit btw, the semantics I had in mind were here Destructuring with `await` - #5 by WebReflection ... that's how I'd expect this to work while awaiting one thing after the other is still possible explicitly in user land ... but then again, if this is a proposal blocker, as requirement, it was in the desirable bucket, not in the must have one.

I agree it's desirable, but it would be very confusing imo if two awaits didn't create two interleaving points (and would almost certainly fail to achieve consensus).

1 Like

Note: there's almost no real difference between these two code snippets (notably, foo() and bar() still operate concurrently):

const {0: a, 1: b} = await Promise.all([foo(), bar()])
const pa = foo()
const pb = bar()
const a = await pa
const b = await pb

You may get perf wins in microbenchmarks, but the main perf wins come from what's already done by simply operating concurrently.

I'm fine with making it sequential, and would just like to see (independent of this) mandatory non-fatal error reporting of lost rejections from Promise.all/etc. for faster (and easier) diagnosis of problems in the backend.

1 Like

I was just wanting this feature. Here is another real-world example using Next.js v15 (relevant docs):

Before

export default async function Page(props) {
  const params = await props.params
  const searchParams = await props.searchParams
  // ...
}

After

export default async function Page({ await params, await searchParams }) {
  // ...
}

And for a more targeted route:

Before

// route: /posts/[id]
export default async function Page({ params }) {
  const id = (await params).id
  // ...
}

After

// route: /posts/[id]
export default async function Page({ await params: { id } }) {
  // ...
}

Also, I didn't see it mentioned elsewhere in this thread, but there was another thread asking for this feature as well: await keyword for destructuring assignment