You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm sure this idea has come up before, but I couldn't find any existing content on it, so I figured I'd put together an issue.
I want to explore the idea of having standardized AsyncContext.Variable objects for specific use cases, much like how Symbol can create arbitrary symbols, but also contains a list of Symbol with specific semantics (ex. Symbol.iterator). Can we define specific AsyncContext variables for particular use cases which might be leveraged by standard implementations?
The main use case I'm thinking of is AbortSignal. Currently, developers much manually pass through AbortSignal into all relevant async APIs.
asyncfunctionparent({ signal }: {signal?: AbortSignal}={}): Promise<void>{awaitchild({ signal });}asyncfunctionchild({ signal }: {signal?: AbortSignal}={}): Promise<void>{awaitgrandchild({ signal });}asyncfunctiongrandchild({ signal }: {signal?: AbortSignal}={}): Promise<void>{constres1=awaitfetch('/one',{ signal });constres2=awaitfetch('/two',{ signal });// ...}
To do this correctly, every async operation needs to accept a signal as an input and properly pass it through to all async functions they call. That's a lot of boilerplate and it's easy to forget.
I'd like to propose a standardized AsyncContext.signal value. In practice, this is just a standard AsyncContext.Variable containing an optional AbortSignal and defaulting to undefined.
Then, anyone can read/write to this context rather than passing through signal in function parameters.
asyncfunctionparent(): Promise<void>{awaitchild();}asyncfunctionchild(): Promise<void>{awaitgrandchild();}asyncfunctiongrandchild(): Promise<void>{constsignal=AsyncContext.abort.get();// Get the signal.// Use it.if(signal){if(signal.aborted)return;signal.addEventListener('abort',()=>{/* ... */},{once: true});}// ...}constsignal=AbortSignal.timeout(1_000);// Create an `AbortSignal`.awaitAsyncContext.abort.run(signal,()=>parent());// Automatically times out after 1sec.
Now anyone could define their own AsyncContext.Variable<AbortSignal | undefined> for this purpose, however by having a standard location for it, we get two additional benefits:
AsyncContext.signal can be shared across libraries and more consistently used in the JavaScript ecosystem (different libraries don't need to define their own variable).
Standard functions can use AsyncContext.signal as well.
Expanding on 2., what if fetch was aware of AsyncContext.signal and listened to it? Then, the following could work:
// No `AbortSignal` anywhere in the function definitions!asyncfunctionparent(): Promise<void>{awaitchild();}asyncfunctionchild(): Promise<void>{awaitgrandchild();}asyncfunctiongrandchild(): Promise<void>{constres1=awaitfetch('/one');// Inherits `AsyncContext.signal`.constres2=awaitfetch('/two');// Inherits `AsyncContext.signal`.// ...}// Run `parent()` and timeout after 1sec.awaitAsyncContext.signal.run(AbortSignal.timeout(1_000),()=>parent());
fetch could read AsyncContext.signal and automatically cancel the active request when it aborts!
This feels very useful to me and fixes a lot of the ecosystem problems with AbortSignal today. Not requiring developers to understand and design this concept into their APIs feels like a huge win. Aborting async operations basically "just works".
There are probably other use cases which might benefit from a standardized AsyncContext.Variable, this is just the most obvious one to me. This particular one is probably more of a follow-up standard after AsyncContext lands on its own, but I think it's worth mentioning here to foster some discussion about the use case and to use this as additional motivation for why AsyncContext could be useful.
The text was updated successfully, but these errors were encountered:
I'm sure this idea has come up before, but I couldn't find any existing content on it, so I figured I'd put together an issue.
I want to explore the idea of having standardized
AsyncContext.Variable
objects for specific use cases, much like howSymbol
can create arbitrary symbols, but also contains a list ofSymbol
with specific semantics (ex.Symbol.iterator
). Can we define specificAsyncContext
variables for particular use cases which might be leveraged by standard implementations?The main use case I'm thinking of is
AbortSignal
. Currently, developers much manually pass throughAbortSignal
into all relevant async APIs.To do this correctly, every async operation needs to accept a signal as an input and properly pass it through to all async functions they call. That's a lot of boilerplate and it's easy to forget.
I'd like to propose a standardized
AsyncContext.signal
value. In practice, this is just a standardAsyncContext.Variable
containing an optionalAbortSignal
and defaulting toundefined
.Then, anyone can read/write to this context rather than passing through
signal
in function parameters.Now anyone could define their own
AsyncContext.Variable<AbortSignal | undefined>
for this purpose, however by having a standard location for it, we get two additional benefits:AsyncContext.signal
can be shared across libraries and more consistently used in the JavaScript ecosystem (different libraries don't need to define their own variable).AsyncContext.signal
as well.Expanding on 2., what if
fetch
was aware ofAsyncContext.signal
and listened to it? Then, the following could work:fetch
could readAsyncContext.signal
and automatically cancel the active request when it aborts!This feels very useful to me and fixes a lot of the ecosystem problems with
AbortSignal
today. Not requiring developers to understand and design this concept into their APIs feels like a huge win. Aborting async operations basically "just works".There are probably other use cases which might benefit from a standardized
AsyncContext.Variable
, this is just the most obvious one to me. This particular one is probably more of a follow-up standard afterAsyncContext
lands on its own, but I think it's worth mentioning here to foster some discussion about the use case and to use this as additional motivation for whyAsyncContext
could be useful.The text was updated successfully, but these errors were encountered: