I have been working with JavaScript Proxies and Promises, and I'm looking for a way to detect whether an object is being awaited using the await keyword or accessed with a chaining operator like .. Currently, JavaScript doesn't seem to have a built-in way to distinguish between these two cases. I was wondering if it would be possible to introduce a new "await trap" or "Promise trap" for Proxies in ECMAScript to handle this scenario.
The main idea is to have a trap that would be called when the object is awaited, allowing the Proxy to take different actions based on whether it's being used as a Promise or as a regular object with chaining.
Here is an example of what I'm trying to achieve:
const handler = {
get(target, prop, receiver) {
// Handle regular properties and chaining
},
await(target) {
// Handle await keyword and Promise resolution
},
};
const p = new Proxy(target, handler);
// Using the object as a Promise
await p;
// Using the object with chaining
p.then;
I would appreciate any thoughts or feedback on this idea. Is there a reason this hasn't been implemented yet, or are there any alternative ways to achieve the same goal?
await is just sugar for a nested Promise .then, and it's not an observable call by design - so no, there's no trap, and it's very intentionally not something you're allowed to interfere with.
Separately, I think it would be a very confusing world if, for a Promise x, await x and return x in an async function and x.then() (modulo someone monkeying with Promise.prototype.then) didn't do the same thing.
Thank you for your response. I understand the design decision behind not having an "await trap" and the importance of consistency in the language.
In my use case, I am trying to build a library that allows asynchronous queries on data structures. The goal is to provide a chained syntax that simplifies the query writing. Using Proxies, I can achieve this as follows:
await root.item('folder').item('subfolder').item('then').value
// same but using proxies:
await proxify(root).folder.subfolder.then; // "then" is the name of the file
However, due to the behavior of await, the only identifier I cannot use in this context is then.
Introducing a Symbol.then as an additional alternative to .then for thanables would also help.
Maybe I just have to think about it more...
I appreciate your insight and will continue exploring different approaches to address this challenge.
Exactly, that would solve my problem.
Proposal-eventual-send would probably solve the problem too, but it's a little harder to understand.
Is that why the proposal was archived?
Just for the record in this thread:
For the same purpose (To not occupy property-names with foreign functionality) I support the idea of a Symbol.toJSON.
The eventual-send proposal is very much not archived. It hasn't see much activity lately, but our production system actually uses a shim for it. It is meant to pair with the wavy-dot proposal to implement promise pipelining (our in our current implementation, a single letter E helper). There are a few posts in this forum discussing solution to this category of problems, some of which where I've posted more details on these 2 proposals.