A lightweight library that provides tools for organizing asynchronous code
—
Convert Node.js callback-style functions to promise-returning functions for better async composition and modern JavaScript patterns.
Transform Node.js callback-style functions into promise-returning functions.
/**
* Convert Node.js callback-style function to promise-returning function
* @param nodeFunc - Function following Node callback pattern (err, value)
* @param options - Boolean for multiple values or Array for named values
* @returns Promisified version of the function
*/
function denodeify(nodeFunc: Function, options?: boolean | Array): Function;import { denodeify } from "rsvp";
const fs = require('fs');
// Convert fs.readFile to promise-based
const readFile = denodeify(fs.readFile);
readFile('myfile.txt', 'utf8')
.then(function(data) {
console.log('File contents:', data);
})
.catch(function(error) {
console.error('Failed to read file:', error);
});
// Original callback version would be:
// fs.readFile('myfile.txt', 'utf8', function(err, data) {
// if (err) console.error(err);
// else console.log(data);
// });When a Node.js function returns multiple success parameters, use the options parameter:
const request = require('request');
// Default - returns only first success parameter
const requestSimple = denodeify(request);
requestSimple('http://example.com').then(function(response) {
// Only gets the response object
});
// With `true` - returns all success parameters as array
const requestArray = denodeify(request, true);
requestArray('http://example.com').then(function(result) {
// result[0] is response object
// result[1] is body
console.log('Status:', result[0].statusCode);
console.log('Body:', result[1]);
});
// With array of names - returns object with named properties
const requestNamed = denodeify(request, ['response', 'body']);
requestNamed('http://example.com').then(function(result) {
console.log('Status:', result.response.statusCode);
console.log('Body:', result.body);
});this Contextconst express = require('express');
const app = express();
// Bind to preserve `this` context
const render = denodeify(app.render.bind(app));
render('template', { data: 'value' })
.then(function(html) {
console.log('Rendered HTML:', html);
});The denodified function inherits from the original function, preserving properties:
const request = denodeify(require('request'));
// Original function properties are preserved
const cookieJar = request.jar(); // Works because of inheritance
request('http://example.com', { jar: cookieJar })
.then(function(response) {
// cookieJar now contains cookies from the response
});const fs = require('fs');
const readFile = denodeify(fs.readFile);
const writeFile = denodeify(fs.writeFile);
// Chain file operations
readFile('input.txt', 'utf8')
.then(function(data) {
const processedData = data.toUpperCase();
return writeFile('output.txt', processedData, 'utf8');
})
.then(function() {
console.log('File processing complete');
})
.catch(function(error) {
console.error('File operation failed:', error);
});
// Compare with callback version:
// fs.readFile('input.txt', 'utf8', function(err, data) {
// if (err) return console.error(err);
// const processedData = data.toUpperCase();
// fs.writeFile('output.txt', processedData, 'utf8', function(err) {
// if (err) return console.error(err);
// console.log('File processing complete');
// });
// });denodeify can handle promises as input arguments:
const processFile = denodeify(someNodeFunction);
// Promise arguments are resolved before calling the original function
processFile(
Promise.resolve('filename.txt'),
Promise.resolve('utf8')
).then(function(result) {
// Both arguments were resolved before calling someNodeFunction
});const fs = require('fs');
const readFile = denodeify(fs.readFile);
readFile('nonexistent.txt')
.catch(function(error) {
if (error.code === 'ENOENT') {
console.log('File not found');
return 'default content';
}
throw error; // Re-throw other errors
})
.then(function(content) {
console.log('Content:', content);
});const fs = require('fs');
const readFile = denodeify(fs.readFile);
const writeFile = denodeify(fs.writeFile);
const stat = denodeify(fs.stat);
const readdir = denodeify(fs.readdir);
// Usage
Promise.all([
readFile('file1.txt', 'utf8'),
readFile('file2.txt', 'utf8'),
stat('file3.txt')
]).then(function([content1, content2, stats]) {
console.log('All operations completed');
});const { exec } = require('child_process');
const execPromise = denodeify(exec);
execPromise('ls -la')
.then(function(result) {
console.log('Command output:', result[0]); // stdout
console.log('Command errors:', result[1]); // stderr
})
.catch(function(error) {
console.error('Command failed:', error);
});// Example with a database library
const db = require('some-db-library');
const query = denodeify(db.query, true); // true for multiple return values
query('SELECT * FROM users WHERE id = ?', [userId])
.then(function(result) {
const rows = result[0];
const fields = result[1];
console.log('Query results:', rows);
});denodeify works in all environments except IE 10 and below due to its use of function inheritance patterns. All properties of the original function remain available on the denodified function.
Install with Tessl CLI
npx tessl i tessl/npm-rsvp