A comprehensive promise library implementing CommonJS Promises/A,B,D specifications for JavaScript
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Methods for accessing properties and calling methods on promised values, enabling object-oriented programming patterns with promises.
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));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 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));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