📚 3 min read
Promisifying Examples ​
Learn how to convert callback-based APIs into Promise-based ones.
Basic Usage ​
typescript
// Basic promisification
function promisify<T>(
fn: (callback: (error: Error | null, result?: T) => void) => void
): () => Promise<T> {
return () =>
new Promise((resolve, reject) => {
fn((error, result) => {
if (error) reject(error);
else resolve(result!);
});
});
}
// Example with setTimeout
const delay = (ms: number): Promise<void> =>
new Promise((resolve) => setTimeout(resolve, ms));
// Example with Node.js fs
const readFileAsync = (path: string): Promise<string> =>
new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', (error, data) => {
if (error) reject(error);
else resolve(data);
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Advanced Patterns ​
Generic Promisification ​
typescript
type Callback<T> = (error: Error | null, result?: T) => void;
function promisifyGeneric<T, A extends any[]>(
fn: (...args: [...A, Callback<T>]) => void
): (...args: A) => Promise<T> {
return (...args: A) =>
new Promise((resolve, reject) => {
fn(...args, (error, result) => {
if (error) reject(error);
else resolve(result!);
});
});
}
// Usage example
const readFile = promisifyGeneric(fs.readFile);
const writeFile = promisifyGeneric(fs.writeFile);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Class Method Promisification ​
typescript
function promisifyMethod<T, A extends any[]>(
target: any,
method: string
): (...args: A) => Promise<T> {
const original = target[method];
return (...args: A) =>
new Promise((resolve, reject) => {
original.call(target, ...args, (error: Error | null, result?: T) => {
if (error) reject(error);
else resolve(result!);
});
});
}
// Usage example
class Database {
query(
sql: string,
callback: (error: Error | null, results?: any[]) => void
): void {
// Implementation...
}
}
const db = new Database();
const queryAsync = promisifyMethod(db, 'query');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Event Emitter Promisification ​
typescript
function promisifyEvent(
emitter: EventEmitter,
eventName: string
): Promise<any> {
return new Promise((resolve, reject) => {
function handler(data: any) {
cleanup();
resolve(data);
}
function errorHandler(error: Error) {
cleanup();
reject(error);
}
function cleanup() {
emitter.removeListener(eventName, handler);
emitter.removeListener('error', errorHandler);
}
emitter.on(eventName, handler);
emitter.on('error', errorHandler);
});
}
// Usage example
async function waitForEvent(emitter: EventEmitter, event: string) {
try {
const data = await promisifyEvent(emitter, event);
console.log(`Event ${event} occurred with data:`, data);
} catch (error) {
console.error(`Error waiting for ${event}:`, error);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Batch Promisification ​
typescript
type AsyncFunction<T> = (...args: any[]) => Promise<T>;
function promisifyAll<T extends object>(
obj: T,
suffix: string = 'Async'
): T & Record<string, AsyncFunction<any>> {
const result = { ...obj } as T & Record<string, AsyncFunction<any>>;
Object.getOwnPropertyNames(obj).forEach((key) => {
const value = (obj as any)[key];
if (typeof value === 'function' && !key.endsWith(suffix)) {
result[`${key}${suffix}`] = promisifyGeneric(value);
}
});
return result;
}
// Usage example
const fs = require('fs');
const fsAsync = promisifyAll(fs);
async function example() {
const data = await fsAsync.readFileAsync('file.txt', 'utf8');
await fsAsync.writeFileAsync('output.txt', data.toUpperCase());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Promisification with Cancellation ​
typescript
interface CancellablePromise<T> extends Promise<T> {
cancel: () => void;
}
function promisifyWithCancel<T>(
fn: (callback: (error: Error | null, result?: T) => void) => () => void
): () => CancellablePromise<T> {
return () => {
let cleanup: (() => void) | null = null;
const promise = new Promise<T>((resolve, reject) => {
cleanup = fn((error, result) => {
if (error) reject(error);
else resolve(result!);
});
}) as CancellablePromise<T>;
promise.cancel = () => {
if (cleanup) cleanup();
};
return promise;
};
}
// Usage example
const cancellableTimeout = promisifyWithCancel<void>((callback) => {
const timeoutId = setTimeout(() => callback(null), 1000);
return () => clearTimeout(timeoutId);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30