Introduction

   Promise is the core of the modern async programming. But the NodeJS is designed before the Promise. So its huge number of async APIs are base on callback. We cannot use them unless we change them promisive, or say promisify. A ideal way is ask Ryan Dahl to change the APIs. Returns a promise instead of throw an error when the callback is not given. But it’s bad to take him from focus on deno. So, we must do it ourselves.

   For the huge number, wrap them one by one is not a good plan. Use what, wrap what is not the best too. We need a general, and as light-weight as better way to make this.

   So I make this:

Declare

function Do( api, ...args )
{
	return new Promise(
		( resolve, reject, )=> api(
			...args,
			( err, response, )=> {
				if( err )
					reject( err, );
				else
					resolve( response, );
			},
		),
	);
}

function Promisify( module, )
{
	const cache= {};
	
	return new Proxy(
		module,
		{
			get( target, key, receiver, ){
				if(!( Reflect.has( target, key, ) ))
					return undefined;
				
				return cache[key] || (
					cache[key]= ( ...args )=> Do(
						Reflect.get( target, key, receiver, ),
						...args,
					)
				);
			},
		},
	);
}

Usage

// Do
const fs= require( 'fs', );


Do( fs.readFile, '/path/to/file', 'utf-8', ).then( /* ... */ );

await Do( fs.readdir, '/path/to/directory', );


// Promisify
const pfs= Promisify( fs );


pfs.readFile( '/path/to/file', 'utf-8', ).then( /* ... */ );

await pfs.readdir( '/path/to/directory', );

Designing Concept

   The async APIs of NodeJS follows a standard: no matter how many the parameters, the last parameter is the callback. And there are two parameters for callback. The first is the error or null, the second is the result. So the function “Do” designed.    But the function “Do”, is not so comfortable for JS programmers. If we can access new APIs just like the old one, it’s better. For this purpose, we can use Proxy to intercept the accessing, and return the promisified API by the Do function. At the last, we cache the promisified API to avoid pfs.readFile !== pfs.readFile.