deferential: Promise/Callback Dual API Helper
deferential is a lightweight JavaScript utility designed to assist in building APIs that support both Node.js-style callbacks and native ES6 Promises. It provides a `Deferred` object, which acts as an intermediate for managing the resolution or rejection of a promise, and a `nodeify` method to conditionally return a promise or invoke a callback. The package is at version 1.0.0, indicating a stable but likely infrequent release cadence given its focused scope and the maturity of native Promise implementations. Its key differentiator lies in offering a minimalistic approach to deferred patterns, avoiding the heavier overhead of full-fledged promise libraries like Q or Bluebird by leveraging native browser/Node.js ES6 Promises. It's particularly useful for adapting existing callback-based code to also expose a promise-based interface without rewriting the core logic.
Common errors
-
ReferenceError: require is not defined in ES module scope
cause Attempting to use `require('deferential')` in a JavaScript file that Node.js interprets as an ES module (e.g., due to `.mjs` extension or `"type": "module"` in `package.json`).fixEnsure your file is treated as a CommonJS module (e.g., `.js` extension without `"type": "module"`) or use Node.js's `import { createRequire } from 'module'; const require = createRequire(import.meta.url); const Deferred = require('deferential');`. -
TypeError: Deferred is not a function
cause This error typically occurs if `deferential` was imported incorrectly (e.g., `import { Deferred } from 'deferential';`) or if the module failed to load.fixVerify that you are using `const Deferred = require('deferential');` in a CommonJS context, and that the package is correctly installed. -
ReferenceError: Promise is not defined
cause The JavaScript environment where `deferential` is being executed does not have a native ES6 Promise implementation.fixAdd a Promise polyfill (e.g., `require('native-promise-only');`) at the entry point of your application before `deferential` is used.
Warnings
- gotcha The 'deferred' pattern, while implemented by `deferential`, is often considered an anti-pattern in modern JavaScript in favor of directly constructing Promises using `new Promise((resolve, reject) => { ... })`.
- gotcha This package is primarily designed for CommonJS environments. Attempting to use `import Deferred from 'deferential';` in a native ES module context in Node.js will result in errors.
- gotcha The package relies on the global availability of an ES6 `Promise` constructor. In very old or non-standard JavaScript environments, a polyfill for `Promise` might be required.
Install
-
npm install deferential -
yarn add deferential -
pnpm add deferential
Imports
- Deferred
import Deferred from 'deferential';
const Deferred = require('deferential'); - Deferred()
const d = new Deferred();
const d = Deferred();
- d.resolver()
fs.readFile(fileName, 'utf8', d.resolve);
fs.readFile(fileName, 'utf8', d.resolver());
Quickstart
const Promise = require('native-promise-only'); // Polyfill for older environments
const fs = require('fs');
const Deferred = require('deferential');
function getFile(fileName, cb) {
const d = Deferred();
fs.readFile(fileName, 'utf8', d.resolver());
return d.nodeify(cb);
}
// Example usage with callback
getFile('myfile.text', function (err, data) {
if (err) return console.error('Callback error:', err.message);
console.log('Callback data:', data.substring(0, 50) + '...');
});
// Example usage with Promise
getFile('myfile.txt')
.then(function (data) {
console.log('Promise data:', data.substring(0, 50) + '...');
})
.catch(function (err) {
console.error('Promise error:', err.message);
});
// To make the example runnable, create a dummy file
fs.writeFileSync('myfile.text', 'This is some dummy content for the deferential example file. It demonstrates how the package can handle both callback-based and promise-based APIs simultaneously. This makes it easier to migrate or support legacy code while offering modern promise interfaces.');
fs.writeFileSync('myfile.txt', 'This is some dummy content for the deferential example file. It demonstrates how the package can handle both callback-based and promise-based APIs simultaneously. This makes it easier to migrate or support legacy code while offering modern promise interfaces.');