When implementing resource cleanup logic, especially disposers for explicit resource management, always design for resilience during error conditions:
When implementing resource cleanup logic, especially disposers for explicit resource management, always design for resilience during error conditions:
SuppressedError
class MyDisposableResource {
#disposed = false;
dispose() {
// ✅ Idempotent - safe to call multiple times
if (this.#disposed) return;
this.#disposed = true;
try {
// Cleanup logic here
console.log('Resource cleaned up');
} catch (error) {
// ✅ Avoid throwing from disposers
console.error('Error during disposal:', error);
// Don't re-throw - this would mask any pending exception
}
}
[Symbol.dispose]() {
// ✅ Delegate to explicit disposal method
this.dispose();
}
}
This pattern ensures resources are cleaned up reliably even during error conditions. By making disposers idempotent and error-safe, you prevent cascading failures where cleanup code compounds the original problem. It’s especially important in using
/await using
blocks where disposers are called automatically during both normal and exceptional exits, with no information about pending exceptions.
Enter the URL of a public GitHub repository