When working with async operations, carefully manage execution context and resource references across await boundaries to prevent context corruption and resource leaks.
When working with async operations, carefully manage execution context and resource references across await boundaries to prevent context corruption and resource leaks.
For execution context, avoid patterns where context enters/exits span async boundaries, as context may not be properly restored after await points. Instead, structure code to contain async operations within the context scope:
// Problematic - context lost across await
if (TRACING_ENABLED) {
span = builtinTracer().startSpan(this.method, { kind: 2 });
context = enterSpan(span);
// await operations here lose context
}
// Better - use IIFE to contain async operations
const old = getAsyncContext();
try {
setAsyncContext('inside operation');
return (async () => {
await asyncOperation();
// context preserved here
})();
} finally {
setAsyncContext(old);
}
For resource management, distinguish between ongoing and future async operations when managing references. Use unref/ref patterns to handle current operations without affecting future ones:
// Unref ongoing reads but not future reads
if (this.unref) {
this.unref(); // Clear current operation references
this.ref(); // Re-establish for future operations
}
This prevents resource leaks while maintaining proper reference counting for subsequent async operations.
Enter the URL of a public GitHub repository