proposal-explicit-resource-management
proposal-explicit-resource-management copied to clipboard
[SUGGESTION]: static `run` method on DisposableStack / AsyncDisposableStack
I think, it could be a great addition to have a static run (not contractual name) method on DisposableStack / AsyncDisposableStack.
Definition:
class AsyncDisposableStack {
// NOT SURE OF THE OPTIMAL IMPLEMENTATION
static async run<GReturn>(
context: (stack: AsyncDisposableStack) => Promise<GReturn> | GReturn,
): Promise<GReturn> {
const stack: AsyncDisposableStack = new AsyncDisposableStack();
let result: GReturn;
try {
result = await context(stack);
} catch (error: unknown) {
try {
await stack.disposeAsync();
} catch (disposeError: unknown) {
throw new SuppressedError(disposeError, error);
}
throw error;
}
await stack.disposeAsync();
return result;
}
// OR MAYBE
static async run<GReturn>(
context: (stack: AsyncDisposableStack) => Promise<GReturn> | GReturn,
): Promise<GReturn> {
const stack: AsyncDisposableStack = new AsyncDisposableStack();
try {
return context(stack);
} finally {
await stack.disposeAsync();
}
}
// ...
}
Example:
await AsyncDisposableStack.run(
async (stack: AsyncDisposableStack): Promise<void> => {
const client = stack.use(/* something AsyncDisposable */);
stack.defer((): void => {
// register something to dispose like an eventListener for example.
});
await client.send('message');
// some other async code
// => if an error is thrown, or the async function return, then the stack is properly disposed.
},
);
What's your opinion ?