CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-call-me-maybe

Let your JS API users either give you a callback or receive a promise

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

Call Me Maybe

Call Me Maybe enables JavaScript APIs to support both callback and promise-based patterns simultaneously. It allows library authors to write promise-based code while automatically providing callback support for users who prefer the traditional error-first callback pattern.

Package Information

  • Package Name: call-me-maybe
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install call-me-maybe

Core Imports

const maybe = require("call-me-maybe");

ES6 Modules (with bundlers or Node.js ES module support):

import maybe from "call-me-maybe";

Basic Usage

const maybe = require("call-me-maybe");

// Use in your API function
function asyncFunc(cb) {
  return maybe(cb, new Promise((resolve, reject) => {
    // Your async logic here
    setTimeout(() => resolve("result"), 100);
  }));
}

// Users can call with callback
asyncFunc((err, result) => {
  if (err) console.error(err);
  else console.log(result); // "result"
});

// Or without callback to get promise
asyncFunc()
  .then(result => console.log(result)) // "result"
  .catch(err => console.error(err));

Capabilities

Dual Interface Function

The core functionality that enables APIs to support both callback and promise patterns.

/**
 * Provides dual callback/promise interface for async functions
 * @param {Function|null|undefined} cb - Optional error-first callback function
 * @param {Promise} promise - Promise to handle
 * @returns {undefined|Promise} Returns undefined when callback provided, otherwise returns the promise
 */
function maybe(cb, promise);

Behavior:

  • If cb is truthy: Executes the promise and calls the callback with error-first parameters
    • On promise fulfillment: cb(null, result)
    • On promise rejection: cb(err)
    • Returns undefined
  • If cb is falsy (null, undefined, false, etc.): Returns the original promise directly

Usage Examples:

Callback pattern:

const maybe = require("call-me-maybe");

function fetchData(cb) {
  return maybe(cb, fetch("/api/data").then(res => res.json()));
}

// With callback
fetchData((err, data) => {
  if (err) {
    console.error("Error:", err);
  } else {
    console.log("Data:", data);
  }
});

Promise pattern:

// Without callback - returns promise
fetchData()
  .then(data => console.log("Data:", data))
  .catch(err => console.error("Error:", err));

// Or with async/await
try {
  const data = await fetchData();
  console.log("Data:", data);
} catch (err) {
  console.error("Error:", err);
}

Complex example with error handling:

function processFile(filename, cb) {
  const filePromise = fs.promises.readFile(filename, 'utf8')
    .then(content => content.toUpperCase())
    .then(processed => ({ filename, content: processed }));
  
  return maybe(cb, filePromise);
}

// Callback style with error handling
processFile('data.txt', (err, result) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.log('File not found');
    } else {
      console.error('Unexpected error:', err);
    }
  } else {
    console.log(`Processed ${result.filename}: ${result.content}`);
  }
});

// Promise style
processFile('data.txt')
  .then(result => console.log(`Processed ${result.filename}: ${result.content}`))
  .catch(err => {
    if (err.code === 'ENOENT') {
      console.log('File not found');
    } else {
      console.error('Unexpected error:', err);
    }
  });

Implementation Details

Async Scheduling

Call Me Maybe uses intelligent async scheduling to ensure callbacks are called asynchronously, preventing potential issues with synchronous callback execution:

  • Uses process.nextTick in Node.js environments
  • Falls back to setImmediate if available (browser with setImmediate polyfill)
  • Falls back to setTimeout(fn, 0) as final option

This ensures consistent asynchronous behavior across all environments.

Error Handling

  • Callback errors are passed as the first parameter following Node.js error-first convention
  • Promise rejections are automatically converted to callback errors
  • Exceptions thrown within callbacks are allowed to bubble up as uncaught exceptions
  • When using callbacks, the function always returns undefined regardless of promise state

Environment Compatibility

  • Node.js: Full support with optimal process.nextTick scheduling
  • Browsers: Full support with fallback scheduling mechanisms
  • CommonJS: Native support via require()
  • ES6 Modules: Support via import statement
  • Zero Dependencies: No external dependencies required
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/call-me-maybe@1.0.x
Publish Source
CLI
Badge
tessl/npm-call-me-maybe badge