📚 2 min read
Promise.finally Examples ​
Learn how to use Promise.finally
for cleanup and resource management.
Basic Usage ​
typescript
// Basic cleanup pattern
async function fetchWithCleanup(url: string) {
const controller = new AbortController();
const { signal } = controller;
try {
return await fetch(url, { signal });
} catch (error) {
console.error('Fetch failed:', error);
throw error;
} finally {
controller.abort();
}
}
// Resource management
async function useResource<T, R>(
resource: T,
work: (resource: T) => Promise<R>,
cleanup: (resource: T) => Promise<void>
): Promise<R> {
try {
return await work(resource);
} finally {
await cleanup(resource);
}
}
Advanced Patterns ​
Database Connection Management ​
typescript
interface Connection {
query: (sql: string) => Promise<any>;
close: () => Promise<void>;
}
class ConnectionPool {
private connections: Connection[] = [];
private inUse = new Set<Connection>();
async acquire(): Promise<Connection> {
// Implementation details...
return {} as Connection;
}
release(connection: Connection): void {
this.inUse.delete(connection);
this.connections.push(connection);
}
}
async function withConnection<T>(
pool: ConnectionPool,
work: (connection: Connection) => Promise<T>
): Promise<T> {
const connection = await pool.acquire();
try {
return await work(connection);
} finally {
pool.release(connection);
}
}
Timer Management ​
typescript
class Timer {
private timers: Set<NodeJS.Timeout> = new Set();
setTimeout(callback: () => void, ms: number): NodeJS.Timeout {
const timer = setTimeout(() => {
this.timers.delete(timer);
callback();
}, ms);
this.timers.add(timer);
return timer;
}
clearAll(): void {
this.timers.forEach((timer) => clearTimeout(timer));
this.timers.clear();
}
}
async function withTimers<T>(work: (timer: Timer) => Promise<T>): Promise<T> {
const timer = new Timer();
try {
return await work(timer);
} finally {
timer.clearAll();
}
}
File Handle Management ​
typescript
interface FileHandle {
write: (data: string) => Promise<void>;
close: () => Promise<void>;
}
async function withFile<T>(
path: string,
work: (file: FileHandle) => Promise<T>
): Promise<T> {
const file: FileHandle = await openFile(path);
try {
return await work(file);
} finally {
await file.close();
}
}
// Usage example
async function processFile(path: string): Promise<string> {
return withFile(path, async (file) => {
// Work with file...
return 'processed content';
});
}
Mutex Lock Management ​
typescript
class Mutex {
private locked = false;
private queue: (() => void)[] = [];
async acquire(): Promise<void> {
if (!this.locked) {
this.locked = true;
return;
}
return new Promise<void>((resolve) => {
this.queue.push(resolve);
});
}
release(): void {
if (this.queue.length > 0) {
const next = this.queue.shift()!;
next();
} else {
this.locked = false;
}
}
}
async function withMutex<T>(mutex: Mutex, work: () => Promise<T>): Promise<T> {
await mutex.acquire();
try {
return await work();
} finally {
mutex.release();
}
}