# Destructuring with \`await\`

**URL:** <https://es.discourse.group/t/destructuring-with-await/1768>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [July 31, 2023, 9:05am UTC](https://es.discourse.group/t/destructuring-with-await/1768 "2023-07-31T09:05:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [July 31, 2023, 9:05am UTC](https://es.discourse.group/t/destructuring-with-await/1768/1 "2023-07-31T09:05:30Z")

</div>

I am not sure this has been discussed already but I find myself often writing repetitive code such as:

```javascript
const thing = await namespace.thing;

```

and I wonder if we could have instead:

```javascript
const {await thing} = namespace;

```

This alone is not super interesting but with namespaces carrying many things it makes destructuring super lovely:

```javascript
const {
  a, b, c,
  await d,
  e,
  await f
} = my.alphabet;

```

Thoughts?

The proposal is pretty much this one with the detail that all awaits should be considered like `Promise.all` and not awaited one after the other (imho) as when dependencies on await is desired users can still split their intent explicitly while defaults should be sane and fast.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [August 1, 2023, 4:56am UTC](https://es.discourse.group/t/destructuring-with-await/1768/2 "2023-08-01T04:56:10Z")

</div>

One potential solution to this problem would be the [await dictionary](https://github.com/tc39/proposal-await-dictionary) proposal, which proposes the addition of a new `Promise.ownProperties()` function. You give it an object, and it'll await all of the promises on that object, returning a new object with the promised values. Presumably, non-promise values would be passed through as-is, the same way they get treated in any other scenario.

So, we could solve your use-case using this function as follows:

```javascript
const { a, b, c, d, e, f } = await Promise.ownProperties(my.alphabet);

```

One disadvantage is that we lose information about which properties were promises and which weren't. Maybe if we had this in combination with a [pick syntax/API](https://github.com/tc39/proposal-object-pick-or-omit), we could get that too with two lines of code, albeit a bit more clunky.

```javascript
// If we have pick syntax
const { a, b, c, e } = my.alphabet;
const { d, f } = await Promise.ownProperties(my.alphabet.{ d, f });

// If we have a pick function
const { a, b, c, e } = my.alphabet;
const { d, f } = await Promise.ownProperties(Object.pick(my.alphabet, ['d', 'f']));

```

I'm wondering if you could expound on your use cases a bit more. I personally haven't found myself having namespaces that had a mix of promises and normal values on there like this.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [August 1, 2023, 7:35am UTC](https://es.discourse.group/t/destructuring-with-await/1768/3 "2023-08-01T07:35:54Z")

</div>

This might be good enough, although it's pretty verbose:

```javascript
const { a, b, c, d, e, f } = await Promise.ownProperties(my.alphabet);

```

This one though:

```javascript
const { d, f } = await Promise.ownProperties(Object.pick(my.alphabet, ['d', 'f']));

```

doesn't offer nothing more than:

```javascript
const [d, f] = Promise.all([my.alphabet.d, my.alphabet.f]);

```

I mean ... we can find many utilities or workarounds but nothing would beat:

```javascript
const { a, b, c, await d, e, await f } = my.alphabet;

```

> One disadvantage is that we lose information about which properties were promises

On the other hand, my syntax proposal explicitly define what should be awaited and what shouldn't, living room for promises that are meant to be left as promised and not resolved.

> I'm wondering if you could expound on your use cases a bit more

We have objects that carry both direct fields and methods/utilities but might need some asynchronous dance to be fully usable (a classic `async init()` or a `ready: new Promise(...)` to signal the object is fully bootstrapped):

```javascript
const {
  type,
  utility,
  await ready
} = new Thing('a-type');

```

this is a pretty common scenario to me, specially for cross realms objects and we have many from the Workers' world ... I hope this makes sense.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [August 1, 2023, 2:40pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/4 "2023-08-01T14:40:37Z")

</div>

I'm a little confused about this.

```js
const { a, b } = obj;

```

... decomposes as

```js
const a = obj.a;
const b = obj.b;

```

..., and this

```js
const c = await obj.c;
...

```

... is something similar to

```js
obj.c.then(retval => {
   const c = retval;
   ...
});

```

... assuming `c` is a property that returns a Promise. Then doesn't it stand to reason that this:

```js
const {a, b, c} = await obj;

```

... should decompose to this:

```js
const a = await obj.a;
const b = await obj.b;
const c = await obj.c;

```

...? The problem with putting `await` on the lhs is that it breaks the convention of use on `await`.

```js
const { a, await b, c } = obj;

```

... looks like it should decompose into:

```js
const a = obj.a;
const await b = obj.b;
const c = obj.c;

```

... which would be both a syntax error and completely insensible. Destructuring spreads the rhs term over each element of the lhs term. With the `await` keyword as part of the rhs term, it would be reasonable to assume it would be spread just the same. Awaiting an expression that doesn't return a promise just resolves immediately with the return value of that expression. So that's not an issue.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [August 1, 2023, 3:00pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/5 "2023-08-01T15:00:15Z")

</div>

> [@rdking](#):
>
> `const {a, b, c} = await obj;`

accordingly to your logic this decompress to:

```javascript
obj.then(result => {
  const a = result.a;
  const b = result.b;
  const c = result.c;
});

```

not sure why you wrote that instead ... my proposal though, is that:

```javascript
const { a, await b, c } = obj;

```

decompress (if this is the right term) into:

```javascript
const { a, c } = obj;
const [b] = await Promise.all([obj.b]);

```

Add any other `await` in destructuring and the logic is the same:

```javascript
const { a, await b, c, d, await e } = obj;

// transpile into
const { a, c, d } = obj;
const [b, e] = await Promise.all([obj.b, obj.c]);

```

I hope the proposal is more clear now.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [August 1, 2023, 3:36pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/6 "2023-08-01T15:36:10Z")

</div>

> [@WebReflection](#):
>
> > [@rdking](#):
> >
> > `const {a, b, c} = await obj;`
> 
> accordingly to your logic this decompress to:
> 
> ```javascript
> obj.then(result => {
> const a = result.a;
> const b = result.b;
> const c = result.c;
> });
> 
> ```

Generally, under normal circumstances, you'd be right. The rhs term is usually resolved into an object before the unrolling happens. However, if you do that with this scenario, you'll be awaiting the wrong thing, just like you suggested. To me at least, since `await` is intended to defer a single assignment until the value to be assigned is resolved, while destructuring is designed to set up multiple assignments from a single object, it makes more sense to give destructuring the higher priority.

Let's take it step by step. In order to process

```js
const {a, b, c} = await obj;

```

you have to unroll it first. That means dealing with the destructuring first, which leads to:

```js
const a = await obj.a;
const b = await obj.b;
const c = await obj.c;
...

```

From there, then you can finally process it, which would look the same as:

```js
obj.a.then(result_a => {
   obj.b.then(result_b => {
      obj.c.then(result_c => {
         const a = result_a;
         const b = result_b;
         const c = result_c;
         ...
      });
   });
});

```

I hope that helps you understand my reasoning here. There's also another small issue that you tripped over with your approach.

> [@WebReflection](#):
>
> ```javascript
> const { a, await b, c } = obj;
> 
> ```
> 
> decompress (if this is the right term) into:
> 
> ```javascript
> const { a, c } = obj;
> const [b] = await Promise.all([obj.b]);
> 
> ```
> 
> Add any other `await` in destructuring and the logic is the same:
> 
> ```javascript
> 
> ```

What happens if the calculation of `b` has side effects that alter the calculation of `c`, or vice-versa? The approach you've taken would change the order of operations, and therefore the result. I know side effects are frowned on, but they exist none-the-less. Please give a little more consideration to the order of operations as well as both the consistency and clarity of intent and usage.

Since `await` is a rhs term, seeing it on the lhs will promote confusion in its usage.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [August 1, 2023, 7:25pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/7 "2023-08-01T19:25:13Z")

</div>

> [@rdking](#):
>
> I hope that helps you understand my reasoning here.

it doesn't because that's not how **current** specs or JS works with `await` ... so I am not sure what you are after there.

> [@rdking](#):
>
> What happens if the calculation of `b` has side effects that alter the calculation of `c`, or vice-versa?

What I've already described ... if there is a need to await destructuring, it's already possible, nothing changes ... if there is no need to await one property after the other (namespaces can have many things in it) it works ... if the namespace knows that c cant work until b is resolved, it can await behind the scene that `b` so everything works as well.

There is no use case left out in my proposal ... everything is possible by developers intent.

> [@rdking](#):
>
> The approach you've taken would change the order of operations

Nope, it changes nothing ... considering that also a getter can return a promise that await on other properties, it literally changes nothing to what's possible already.

> [@rdking](#):
>
> Please give a little more consideration to the order of operations as well as both the consistency and clarity of intent and usage.

I did ... everything is the same as it is these days for namespaces with promises except the destructuring can group AOT what to await for.

> [@rdking](#):
>
> Since `await` is a rhs term, seeing it on the lhs will promote confusion in its usage.

I was more confused by you thinking, or showing, that `await obj` result in awaiting every property of that obj ... to be honest ... my proposal is way simpler, not disruptive, and it addresses all use cases.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [August 1, 2023, 8:18pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/8 "2023-08-01T20:18:53Z")

</div>

> [@WebReflection](#):
>
> What I've already described ... if there is a need to await destructuring, it's already possible, nothing changes ... if there is no need to await one property after the other (namespaces can have many things in it) it works ... if the namespace knows that c cant work until b is resolved, it can await behind the scene that `b` so everything works as well.

The thing about `await` is that it does in fact stop execution of the current function. If you `await` several consecutive assignments, subsequent assignments are not attempted until `await` returns, as if everything that follows `await` is in the `.then()` of the promise being awaited.

I understand that

```js
const {a, b, c} = await expression;

```

is already valid ES. That's part and parcel of the confusion I have with your request. What you seem to want to do, given the way `await` is used in the language, is more inline with the alternative description of how to resolve this kind of assignment. Trying to use `await` as a lhs keyword to affect the processing of a rhs expression when rhs is always processed first **makes no sense**. This is what I've been trying to point out to you.

The only way I can see what you're attempting as something reasonable is if it required the renaming style of destructuring to work. Something like this:

```js
const {a, await b: b, c} = obj;

```

The reason I can see this as valid is because the renaming form of destructuring specifies a rhs property name separately from the lhs variable declaration. In this case, it's still relatively clear that the use of await only applies to the rhs term. Then it can be considered reasonable to resolve the above to:

```js
const a = obj.a;
const b = await obj.b;
const c = obj.c;

```

However, as I said before, order of operations must be maintained as anything following `await` essentially appears in the `.then()` handler of the promise being awaited.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [August 1, 2023, 8:45pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/9 "2023-08-01T20:45:15Z")

</div>

> [@rdking](#):
>
> The thing about `await` is that it does in fact stop execution of the current function. If you `await` several consecutive assignments, subsequent assignments are not attempted until `await` returns, as if everything that follows `await` is in the `.then()` of the promise being awaited.

are you explaining me how `await` works?

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [August 1, 2023, 8:51pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/10 "2023-08-01T20:51:17Z")

</div>

> [@rdking](#):
>
> The only way I can see what you're attempting as something reasonable is if it required the renaming style of destructuring to work. Something like this:
> 
> ```javascript
> const {a, await b: b, c} = obj;
> 
> ```
> 
> The reason I can see this as valid is because the renaming form of destructuring specifies a rhs property name separately from the lhs variable declaration. In this case, it's still relatively clear that the use of await only applies to the rhs term.

this would work for me, but it also doesn't address the OP intent to avoid redundant and verbose operations ... the `b` example is fine, `{await somethingMeaningful: somethingMeaningful}` is overly awkward ... yet it's better than nothing, so if you think that works due lhs VS rhs gotchas, it's OK to me ... but destructuring is all about lhs being parsed after rhs, as you pointed out, so I am not sure I am following why, without property re-naming, it can't be possible ... but if you know the why, I trust you that's not possible with current parser.

**edit** on a second though, I don't understand why `{a: _a, await b: _b, c: _c}` is fine, but the parser can't implicitly do the same with `{a, await b, c}` and when `: _b` is written, overload that implicitly added `await b: b` ...

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [August 1, 2023, 9:14pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/11 "2023-08-01T21:14:46Z")

</div>

> [@WebReflection](#):
>
> **edit** on a second though, I don't understand why `{a: _a, await b: _b, c: _c}` is fine, but the parser can't implicitly do the same with `{a, await b, c}` and when `: _b` is written, overload that implicitly added `await b: b` ...

Maybe I wasn't clear enough....  
What I've been referring to is the mental model of operation around the use of `await`. The key points are these:

1. Its a rhs keyword only.
2. It defers the operation of subsequent statements within the same function.

The parser can easily do the operation the way you've described it (barring the order of operations issues), but that's not the big problem. The big problem is in how it breaks the mental model of what's going on. If `await` can be used with a lhs term, then exactly what operation is being deferred? The point of forcing the renaming form of destructuring is about keeping it visually clear that what's being awaited is the rhs term, and has nothing to do with the lhs. Clarity is almost as important as functionality in programming (especially these days).

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [August 1, 2023, 9:30pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/12 "2023-08-01T21:30:40Z")

</div>

> [@rdking](#):
>
> Let's take it step by step. In order to process
> 
> ```javascript
> const {a, b, c} = await obj;
> 
> ```
> 
> you have to unroll it first. That means dealing with the destructuring first, which leads to:
> 
> ```javascript
> const a = await obj.a;
> const b = await obj.b;
> const c = await obj.c;
> 
> ```

This model doesn't quite hold because:

```javascript
const {a,b} = foo();

```

Doesn't de sugar to

```javascript
const a = foo().a;
const b = foo().b;

```

it's

```javascript
const tmp = foo();
const a = tmp.a;
const b = tmp.b;

```

The RHS is not distributed across the LHS.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [August 1, 2023, 10:29pm UTC](https://es.discourse.group/t/destructuring-with-await/1768/13 "2023-08-01T22:29:48Z")

</div>

You’re simply incorrect here; await is not always on the RHS. See for await of, and await using, and `const { x = await y } = o`.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [August 2, 2023, 12:32am UTC](https://es.discourse.group/t/destructuring-with-await/1768/14 "2023-08-02T00:32:46Z")

</div>

🤔 Nice technicality. You almost got me with that one. Doesn't this decode to:

```js
const x = o.x || await y;

```

? If it weren't for the default value assignment, you'd be right. However, local to its containing expression, it's still an RHS use of `await`. If you can show me a use of `await` that appears only on the lhs of its containing expression, then you'll convince me. 😄

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [August 2, 2023, 12:47am UTC](https://es.discourse.group/t/destructuring-with-await/1768/15 "2023-08-02T00:47:04Z")

</div>

I mentioned two.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [August 2, 2023, 1:33am UTC](https://es.discourse.group/t/destructuring-with-await/1768/16 "2023-08-02T01:33:44Z")

</div>

Took a moment to look at both of those. They're both of the general format `await expression`. It's really hair splitting, but even this doesn't count as a lhs await as in these expressions, there's no lhs to mention. They're both compound expressions with an inner assignment as the sub-expression. So, still no.

However, that does put up evidence for a prior art syntax that would make sense for what the OP seems to be trying to do, namely:

```js
await const {a, b, c} = obj;

```

This would effectively do what seems to be intended (have promises of the target properties resolved before assignment) while staying consistent with notations that currently exist in ES.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [August 2, 2023, 2:06am UTC](https://es.discourse.group/t/destructuring-with-await/1768/17 "2023-08-02T02:06:35Z")

</div>

Let me try to say what I'm thinking a different way. For me, the thing to the right of the `await` keyword must be an expression that resolves to either a Promise instance, a "then-able" object, or a first class value that can be wrapped and returned by a Promise. Arrangements that try to break this convention will invariably leave me a bit uncomfortable with the notation.

```js
for await(const a of foo()) {...}

```

This works because what's being awaited is the expression `const a of foo()`, meaning `foo()` is re-evaluated and awaited on each loop, as opposed to

```js
for (const a of await foo()) {...}

```

which would only evaluate and `await` `foo()` once, using the result for each iteration.

I just don't see the sense in something like:

```js
const {await a} = obj;

```

because

```js
const a = obj.(await a);

```

is invalid syntax, and

```js
const await a = obj.a;

```

just doesn't make sense given that from the `=` on, everything is optional.

```js
let await a;

```

seems like it would be valid syntax if `await` can be used as a lhs keyword. That's the problem I have.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [August 2, 2023, 2:55am UTC](https://es.discourse.group/t/destructuring-with-await/1768/18 "2023-08-02T02:55:11Z")

</div>

@ljharb actually mentioned three. [await using](https://github.com/tc39/proposal-explicit-resource-management) isn't in the language yet, but they're planning on adding it soon. This one's especially odd because the thing being awaited is the value being assigned to the variable, but when the awaiting actually happens is at the end of the block (at least, this is how I understand it).

For me, "await" just means that we're pausing the function until a promise (or thenable/whatever) finishes. I don't feel like every syntax we invent that pauses the function for a promise/thing must use "await" in the way you're describing. For me, the "const { await x } = y" syntax intuitively make sense - we're destructuring the object and awaiting for some of the destructured promises to resolve.

I'm just not sure I'm completely on board with it, not because it's unintuitive, but because I don't know if it's worth adding new syntax to solve this problem.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [August 2, 2023, 7:53am UTC](https://es.discourse.group/t/destructuring-with-await/1768/19 "2023-08-02T07:53:30Z")

</div>

I'll try to give a concrete example, which is our daily code to deal with.

There is a definition per each interpreter, where an interpreter is provided via a module, which in turns can create different "sandboxes" ... they all do something like this:

```js
// import the interpreter and returns a normalized namespace
// able to run code sync or async
function getInterpreter(url) {
  return {
    module: import(url),
    run: (sandbox, code) => sandbox.evalute(code),
    runAsync: (sandbox, code) => sandbox.evaluate(code, {async: true})
  };
}

// how things are done now ...
async function createSandbox(moduleURL) {
  const interpreter = getInterpreter(moduleURL);
  const {run, runAsync} = interpreter;
  const module = await interpreter.module;
  const sandbox = await module.createSandBox();
  return {
    run: run.bind(null, sandbox),
    runAsync: runAsync.bind(null, sandbox)
  };
}

// usage
const pyodide = await createSandbox('./pyodide.mjs');
pyodide.run(pythonCode);

```

There other cases where both loading the module / sandbox requires fetching config files to bootstrap and so on ... we're manually orchestrating `Promise.all([...])` here and there to boost bootstrap and use parallelism as much as we can ... now, with my proposal:

```js
async function createSandbox(moduleURL) {
  const {
    run, runAsync,
    await module: { createSandBox }
  } = await getInterpreter(moduleURL);
  const sandbox = await createSandBox();
  return {
    run: run.bind(null, sandbox),
    runAsync: runAsync.bind(null, sandbox)
  };
}

```

Now, when it comes to namespaces carrying lazy imports things become more interesting:

```js
// lazy importMaps in JS (one that works in Workers too)
const urls = {
  'utils': './path/utils.js',
  'lib': 'https://esm.sh/lib',
  'poly': 'https://esm.sh/poly'
};

// handy proxy for lazy imports
const modules = new Proxy(Object.prototype, {
  get: (_, module) => import(urls[module])
});

// file X
const {
  await utils: { path, fs },
  await poly
} = modules;

// file Y
const { await lib } = modules;

```

So now we have a thin layer able to hot-swap loaded modules (change `urls` fields when/if needed) or lazy load all dependencies with ease, allowing modules to be destructured like an import could, or better, exactly like a dynamic `const { stuff } = await import(url)` would.

Is any of these use cases interesting? I find the latter one specially compelling for both prod and dev cases.

**edit** P.S. this latter example explicitly shows the intent of the proposal:

- it is **not desired** to await all properties of an object ... only destructured properties with explicit `await` should be awaited
- it is **very desired** to have all destructured _awaited_ properties to be grouped as single `Promise.all([...])` operation
- it is still possible to attach or return, via the namespace, properties that are not promises, or promises themselves that should not be awaited during destructuring

Any deviation from any of these points will likely make the effort futile and the feature less interesting, imho.

**edit2** the only "complexity" I see for this proposal is the case:

```js
const {
          ┏━━━━━━━━━━━━━━━━━━━━━━━━┓
  await utils: { path, fs, await nested },
  await poly
} = modules;

```

The "obvious" solution I see is that `utils` should be group-awaited with `poly` and then its nested `await` should be grouped / awaited once `utils` is resolved ... in this case the `Promise.all` might not branch all levels equally, if difficult, but ergonomics will still be pretty awesome and easy on the eyes with way less boilerplate needed in general.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [August 2, 2023, 8:53am UTC](https://es.discourse.group/t/destructuring-with-await/1768/20 "2023-08-02T08:53:28Z")

</div>

> [@WebReflection](#):
>
> ```javascript
> const urls = {
> 'utils': './path/utils.js',
> 'lib': 'https://esm.sh/lib',
> 'poly': 'https://esm.sh/poly'
> };
> 
> // handy proxy for lazy imports
> const modules = new Proxy(Object.prototype, {
> get: (_, module) => import(urls[module])
> });
> 
> ```

for history sake, I'd like to write down a more complete/concrete example for the lazy modules pattern that would work in Workers too:

```js
// use a map or a literal
const urls = new Map([
  ['utils', './path/utils.js'],
  ['lib', 'https://esm.sh/lib'],
  ['poly', 'https://esm.sh/poly'],
]);

// allow loading relative or absolute modules too
const modules = new Proxy(Object.prototype, {
  get: (_, module) => import(
    urls.has(module) ?
      urls.get(module) :
      module
  )
});

// above changes allow this to work too
const {
  await utils: { path, fs },
  await ['./thing.js']: thing
} = modules;

```

I _think_ if this syntax would be allowed/possible it would make destructuring in JS extremely lovely to work with. Thanks for at least considering this proposal.

[Next page](https://es.discourse.group/t/destructuring-with-await/1768.md?page=2)
