@jspod.dev/defer
v0.0.1
Published
Deferred execution — register async cleanup callbacks that run on scope exit
Maintainers
Readme
@jspod.dev/defer
Register async cleanup callbacks inside a scope — they run automatically
when the scope exits, whether it resolved or threw. Modelled on Go's defer.
Concept
Without defer, cleanup requires careful try/finally nesting:
const file = await fs.open('data.json');
try {
const tmp = await mkdtemp();
try {
await process(file, tmp);
} finally {
await fs.rm(tmp, { recursive: true });
}
} finally {
await file.close();
}With defer, register cleanup next to acquisition — scope exit handles the rest:
import { defer } from '@jspod.dev/defer';
await defer(async (def) => {
const file = await fs.open('data.json');
def(() => file.close());
const tmp = await mkdtemp();
def(() => fs.rm(tmp, { recursive: true }));
await process(file, tmp);
});Callbacks run in LIFO order — last registered, first executed. Each is fully awaited before the next begins.
Install
npm install @jspod.dev/deferAPI
defer(scope: Scope): Promise<void>| Type | Definition |
| ---------- | ------------------------------------------ |
| Scope | (def: Deferred) => void \| Promise<void> |
| Deferred | (fn: Callback) => void |
| Callback | () => void \| Promise<void> |
def throws TypeError if passed a non-function, and Error if called
after the scope has settled.
Error handling
All callbacks run even if some throw. Errors are collected and reported after the last callback:
| Scope | Cleanup failures | Result |
| ------ | ---------------- | ------------------------------------------------------ |
| ok | 0 | resolves |
| ok | 1 | rejects with that error |
| ok | 2+ | rejects with AggregateError(errors) |
| throws | 0 | rejects with scope error |
| throws | 1+ | rejects with AggregateError([scopeError, ...errors]) |
await defer(async (def) => {
def(() => {
throw new Error('cleanup failed');
});
throw new Error('scope failed');
}).catch((err) => {
// AggregateError
// err.errors[0] — scope error
// err.errors[1] — cleanup error
});License
AGPL-3.0
