CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-q

A comprehensive promise library implementing CommonJS Promises/A,B,D specifications for JavaScript

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

nodejs.mddocs/

Node.js Integration

Comprehensive Node.js callback integration for converting existing callback-based APIs to promises and integrating with the Node.js ecosystem.

Capabilities

Callback Function Conversion

Converts Node.js callback-style functions to promise-returning functions.

/**
 * Wraps Node-style callback function to return promises
 * @param callback - Node.js callback function (error, result) => void
 * @param pattern - Optional parameter processing pattern
 * @returns Promise-returning version of the function
 */
function Q.denodeify(callback, pattern);

Usage Examples:

const Q = require("q");
const fs = require("fs");

// Convert filesystem functions
const readFile = Q.denodeify(fs.readFile);
const writeFile = Q.denodeify(fs.writeFile);
const stat = Q.denodeify(fs.stat);

// Use converted functions
readFile("package.json", "utf8")
  .then(data => JSON.parse(data))
  .then(json => console.log("Package name:", json.name))
  .catch(error => console.error("Read error:", error));

// Convert custom callback functions
function oldStyleFunction(param1, param2, callback) {
  setTimeout(() => {
    if (param1 && param2) {
      callback(null, param1 + param2);
    } else {
      callback(new Error("Invalid parameters"));
    }
  }, 100);
}

const newStyleFunction = Q.denodeify(oldStyleFunction);

newStyleFunction("Hello", " World")
  .then(result => console.log(result)) // "Hello World"
  .catch(error => console.error(error));

// Convert with pattern (for special cases)
const execFile = Q.denodeify(require("child_process").execFile);
execFile("ls", ["-la"])
  .then(stdout => console.log(stdout))
  .catch(error => console.error("Command failed:", error));

Method Invocation

Calls Node.js style methods on objects and returns promises.

/**
 * Calls Node-style method and returns promise
 * @param object - Object containing the method
 * @param name - Method name to call
 * @param ...args - Arguments to pass to method
 * @returns Promise for method result
 */
function Q.ninvoke(object, name, ...args);

/**
 * Calls Node-style method on fulfilled object
 * @param name - Method name to call
 * @param ...args - Arguments to pass to method
 * @returns Promise for method result
 */
promise.ninvoke(name, ...args);

Usage Examples:

const Q = require("q");
const fs = require("fs");

// Static method invocation
Q.ninvoke(fs, "readFile", "config.json", "utf8")
  .then(data => JSON.parse(data))
  .then(config => console.log("Config loaded:", config))
  .catch(error => console.error("Config load failed:", error));

// Instance method invocation with promise of object
const redisClient = getRedisClient();

Q.resolve(redisClient)
  .ninvoke("get", "user:123")
  .then(userData => {
    if (userData) {
      return JSON.parse(userData);
    }
    throw new Error("User not found");
  })
  .then(user => console.log("User:", user))
  .catch(error => console.error("Redis error:", error));

// Chaining method calls
const dbConnection = connectToDatabase();

Q.resolve(dbConnection)
  .ninvoke("query", "SELECT * FROM users WHERE active = ?", [true])
  .then(users => {
    console.log(`Found ${users.length} active users`);
    return Q.ninvoke(dbConnection, "query", 
      "UPDATE users SET last_seen = NOW() WHERE active = ?", [true]);
  })
  .then(result => console.log("Updated timestamps"))
  .catch(error => console.error("Database error:", error));

Promise to Callback Conversion

Converts promises back to Node.js callback style for integration with callback-expecting code.

/**
 * Converts promise to Node-style callback pattern
 * @param nodeback - Node.js style callback function (error, result) => void
 * @returns void (calls nodeback with result)
 */
promise.nodeify(nodeback);

Usage Examples:

const Q = require("q");

// Convert promise to callback for legacy API
function legacyFunction(callback) {
  const promise = fetchUserData()
    .then(user => processUser(user))
    .then(result => ({ success: true, data: result }))
    .catch(error => ({ success: false, error: error.message }));

  promise.nodeify(callback);
}

// Use with traditional callback patterns
legacyFunction((error, result) => {
  if (error) {
    console.error("Operation failed:", error);
  } else {
    console.log("Operation result:", result);
  }
});

// Integration with Express.js middleware
function promiseMiddleware(req, res, next) {
  authenticateUser(req.headers.authorization)
    .then(user => {
      req.user = user;
      return user;
    })
    .nodeify(next); // Calls next() on success, next(error) on failure
}

// Callback-style wrapper for promise-based function
function fetchDataCallback(userId, callback) {
  Q.resolve(userId)
    .then(id => validateUserId(id))
    .then(id => fetchFromDatabase(id))
    .then(data => processData(data))
    .nodeify(callback);
}

// Using the callback wrapper
fetchDataCallback("user123", (error, data) => {
  if (error) {
    console.error("Fetch failed:", error);
  } else {
    console.log("Data received:", data);
  }
});

Deferred Node.js Integration

Creating Node.js compatible resolvers from deferred objects.

/**
 * Creates Node-style callback resolver from deferred
 * @param unpack - Optional flag to unpack single-element arrays
 * @returns Node.js callback function
 */
deferred.makeNodeResolver(unpack);

Usage Examples:

const Q = require("q");
const fs = require("fs");

// Use deferred with Node.js APIs
function readFilePromise(filename) {
  const deferred = Q.defer();
  const nodeCallback = deferred.makeNodeResolver();
  
  fs.readFile(filename, "utf8", nodeCallback);
  
  return deferred.promise;
}

// With unpacking for single results
function statFilePromise(filename) {
  const deferred = Q.defer();
  const nodeCallback = deferred.makeNodeResolver(true);
  
  fs.stat(filename, nodeCallback);
  
  return deferred.promise;
}

// Complex integration example
function executeQuery(sql, params) {
  const deferred = Q.defer();
  const nodeCallback = deferred.makeNodeResolver();
  
  database.query(sql, params, (error, results, fields) => {
    if (error) {
      nodeCallback(error);
    } else {
      nodeCallback(null, { results, fields });
    }
  });
  
  return deferred.promise;
}

// Using the promise-wrapped function
executeQuery("SELECT * FROM users WHERE id = ?", [123])
  .then(({ results, fields }) => {
    console.log("Query results:", results);
    console.log("Field info:", fields);
  })
  .catch(error => console.error("Query failed:", error));

Common Integration Patterns

File System Operations

const Q = require("q");
const fs = require("fs");
const path = require("path");

// Create promise-based fs operations
const readFile = Q.denodeify(fs.readFile);
const writeFile = Q.denodeify(fs.writeFile);
const readdir = Q.denodeify(fs.readdir);
const stat = Q.denodeify(fs.stat);

// Complex file operations
function processDirectory(dirPath) {
  return readdir(dirPath)
    .then(files => {
      const filePromises = files.map(file => {
        const fullPath = path.join(dirPath, file);
        return stat(fullPath)
          .then(stats => ({ name: file, path: fullPath, stats }));
      });
      return Q.all(filePromises);
    })
    .then(fileInfos => {
      const textFiles = fileInfos.filter(info => 
        info.stats.isFile() && path.extname(info.name) === ".txt"
      );
      return textFiles;
    });
}

Database Integration

const Q = require("q");

// Wrap database connection methods
function createDbWrapper(connection) {
  return {
    query: Q.denodeify(connection.query.bind(connection)),
    beginTransaction: Q.denodeify(connection.beginTransaction.bind(connection)),
    commit: Q.denodeify(connection.commit.bind(connection)),
    rollback: Q.denodeify(connection.rollback.bind(connection))
  };
}

// Use wrapped database
const db = createDbWrapper(mysqlConnection);

function updateUserWithTransaction(userId, userData) {
  return db.beginTransaction()
    .then(() => db.query("UPDATE users SET ? WHERE id = ?", [userData, userId]))
    .then(result => {
      if (result.affectedRows === 0) {
        throw new Error("User not found");
      }
      return db.commit();
    })
    .catch(error => {
      return db.rollback().then(() => {
        throw error;
      });
    });
}

Install with Tessl CLI

npx tessl i tessl/npm-q

docs

advanced.md

collections.md

core-promises.md

flow-control.md

functional.md

index.md

nodejs.md

promise-chains.md

property-access.md

queue.md

state-inspection.md

tile.json