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

property-access.mddocs/

Property and Method Access

Methods for accessing properties and calling methods on promised values, enabling object-oriented programming patterns with promises.

Capabilities

Property Access

Methods for accessing properties from promised objects.

/**
 * Gets property from fulfilled value
 * @param name - Property name to access
 * @returns Promise for the property value
 */
promise.get(name);

/**
 * Gets property keys from fulfilled object value
 * @returns Promise for array of property keys
 */
promise.keys();

Usage Examples:

const Q = require("q");

// Basic property access
const userPromise = Q.resolve({
  name: "Alice",
  email: "alice@example.com",
  age: 30,
  preferences: { theme: "dark", language: "en" }
});

userPromise.get("name")
  .then(name => console.log("User name:", name)); // "Alice"

userPromise.get("email")
  .then(email => sendWelcomeEmail(email));

// Nested property access (requires chaining)
userPromise.get("preferences")
  .then(preferences => preferences.theme)
  .then(theme => console.log("User theme:", theme)); // "dark"

// Get all property keys
userPromise.keys()
  .then(keys => console.log("User properties:", keys));
  // ["name", "email", "age", "preferences"]

// Conditional property access
function getProperty(objectPromise, propertyName, defaultValue) {
  return objectPromise.get(propertyName)
    .catch(() => defaultValue);
}

getProperty(userPromise, "nickname", "Unknown")
  .then(nickname => console.log("Nickname:", nickname));

// Dynamic property access
function extractUserInfo(userPromise, fields) {
  const extractions = fields.map(field => 
    userPromise.get(field).catch(() => null)
  );
  
  return Q.all(extractions).then(values => {
    const result = {};
    fields.forEach((field, index) => {
      result[field] = values[index];
    });
    return result;
  });
}

extractUserInfo(userPromise, ["name", "email", "phone", "address"])
  .then(info => console.log("Extracted info:", info));

Method Invocation

Methods for calling functions and methods on promised values.

/**
 * Calls method on fulfilled value with arguments
 * @param name - Method name to call
 * @param ...args - Arguments to pass to the method
 * @returns Promise for the method result
 */
promise.invoke(name, ...args);

/**
 * Calls fulfilled value as function with apply semantics
 * @param thisp - Context object (this value)
 * @param args - Array of arguments
 * @returns Promise for the function result
 */
promise.apply(thisp, args);

/**
 * Calls fulfilled value as function with call semantics
 * @param thisp - Context object (this value)
 * @param ...args - Arguments to pass to function
 * @returns Promise for the function result
 */
promise.call(thisp, ...args);

/**
 * Returns bound function for future calls
 * @param thisp - Context object (this value)
 * @param ...args - Arguments to pre-bind
 * @returns Promise for bound function
 */
promise.bind(thisp, ...args);

Usage Examples:

const Q = require("q");

// Method invocation on objects
const stringPromise = Q.resolve("hello world");

stringPromise.invoke("toUpperCase")
  .then(result => console.log(result)); // "HELLO WORLD"

stringPromise.invoke("substring", 0, 5)
  .then(result => console.log(result)); // "hello"

stringPromise.invoke("split", " ")
  .then(words => console.log("Words:", words)); // ["hello", "world"]

// Method invocation on complex objects
const arrayPromise = Q.resolve([1, 2, 3, 4, 5]);

arrayPromise.invoke("map", x => x * 2)
  .then(doubled => console.log("Doubled:", doubled)); // [2, 4, 6, 8, 10]

arrayPromise.invoke("filter", x => x > 3)
  .then(filtered => console.log("Filtered:", filtered)); // [4, 5]

arrayPromise.invoke("reduce", (acc, val) => acc + val, 0)
  .then(sum => console.log("Sum:", sum)); // 15

// Function application patterns
const calculatorPromise = Q.resolve({
  add: function(a, b) { return this.precision ? Math.round(a + b) : a + b; },
  precision: true
});

// Using apply
calculatorPromise.get("add")
  .apply(calculatorPromise, [3.7, 4.3])
  .then(result => console.log("Applied result:", result));

// Using call
calculatorPromise.get("add")
  .call(calculatorPromise, 3.7, 4.3)
  .then(result => console.log("Called result:", result));

// Function binding
const mathFunctionPromise = Q.resolve(Math.pow);

mathFunctionPromise.bind(null, 2) // Bind first argument to 2
  .then(powerOfTwo => {
    return Q.all([
      powerOfTwo(3), // 2^3 = 8
      powerOfTwo(4), // 2^4 = 16
      powerOfTwo(5)  // 2^5 = 32
    ]);
  })
  .then(results => console.log("Powers of 2:", results));

// Complex method chaining
const userServicePromise = fetchUserService();

userServicePromise
  .invoke("authenticate", "user123", "password")
  .then(authenticated => {
    if (authenticated) {
      return userServicePromise.invoke("getUserProfile", "user123");
    } else {
      throw new Error("Authentication failed");
    }
  })
  .then(profile => {
    console.log("User profile:", profile);
    return userServicePromise.invoke("updateLastLogin", profile.id);
  })
  .catch(error => console.error("User service error:", error));

Advanced Property Patterns

Advanced patterns for working with object properties in promise chains.

const Q = require("q");

// Property extraction utility
function extractProperties(objectPromise, propertyPaths) {
  const extractions = propertyPaths.map(path => {
    const keys = path.split(".");
    let current = objectPromise;
    
    keys.forEach(key => {
      current = current.get(key);
    });
    
    return current.catch(() => undefined);
  });
  
  return Q.all(extractions).then(values => {
    const result = {};
    propertyPaths.forEach((path, index) => {
      result[path] = values[index];
    });
    return result;
  });
}

// Usage
const complexObjectPromise = Q.resolve({
  user: {
    profile: {
      name: "John",
      contact: {
        email: "john@example.com",
        phone: "555-0123"
      }
    },
    settings: {
      theme: "dark",
      notifications: true
    }
  }
});

extractProperties(complexObjectPromise, [
  "user.profile.name",
  "user.profile.contact.email",
  "user.settings.theme"
]).then(extracted => console.log("Extracted:", extracted));

// Method chaining helper
function chainMethods(objectPromise, methodCalls) {
  return methodCalls.reduce((promise, { method, args = [] }) => {
    return promise.invoke(method, ...args);
  }, objectPromise);
}

// Usage
const stringBuilderPromise = Q.resolve("hello");

chainMethods(stringBuilderPromise, [
  { method: "toUpperCase" },
  { method: "split", args: [""] },
  { method: "reverse" },
  { method: "join", args: [""] }
]).then(result => console.log("Processed string:", result)); // "OLLEH"

// Property validation
function validateObjectShape(objectPromise, requiredProperties) {
  return objectPromise.keys().then(availableKeys => {
    const missing = requiredProperties.filter(prop => 
      !availableKeys.includes(prop)
    );
    
    if (missing.length > 0) {
      throw new Error(`Missing required properties: ${missing.join(", ")}`);
    }
    
    return objectPromise;
  });
}

// Usage
const configPromise = loadConfiguration();

validateObjectShape(configPromise, ["host", "port", "database"])
  .then(config => {
    console.log("Configuration is valid");
    return initializeWithConfig(config);
  })
  .catch(error => console.error("Configuration error:", error));

Object Transformation Patterns

Patterns for transforming objects through property access and method calls.

const Q = require("q");

// Object mapping utility
function mapObjectProperties(objectPromise, mappings) {
  const promises = Object.keys(mappings).map(newKey => {
    const mapping = mappings[newKey];
    
    if (typeof mapping === "string") {
      // Simple property rename
      return objectPromise.get(mapping).then(value => ({ [newKey]: value }));
    } else if (typeof mapping === "function") {
      // Transform with function
      return objectPromise.then(obj => ({ [newKey]: mapping(obj) }));
    } else if (mapping.property && mapping.transform) {
      // Property with transformation
      return objectPromise.get(mapping.property)
        .then(mapping.transform)
        .then(value => ({ [newKey]: value }));
    }
  });
  
  return Q.all(promises).then(mappedObjects => {
    return Object.assign({}, ...mappedObjects);
  });
}

// Usage
const rawUserPromise = Q.resolve({
  firstName: "John",
  lastName: "Doe",
  emailAddress: "john.doe@example.com",
  birthDate: "1990-01-15"
});

mapObjectProperties(rawUserPromise, {
  fullName: obj => `${obj.firstName} ${obj.lastName}`,
  email: "emailAddress",
  age: {
    property: "birthDate",
    transform: birthDate => {
      const birth = new Date(birthDate);
      const today = new Date();
      return today.getFullYear() - birth.getFullYear();
    }
  }
}).then(transformedUser => {
  console.log("Transformed user:", transformedUser);
  // { fullName: "John Doe", email: "john.doe@example.com", age: 34 }
});

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