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
Advanced features including low-level dispatch operations, pass-by-copy semantics, timing estimates, and specialized promise operations.
Generic operation dispatch system for advanced promise manipulation.
/**
* Generic operation dispatch on fulfilled value
* @param op - Operation name to dispatch
* @param args - Arguments for the operation
* @returns Promise for operation result
*/
promise.dispatch(op, args);
/**
* Low-level dispatch without promise wrapping
* @param resolve - Resolver function for the result
* @param op - Operation name to dispatch
* @param args - Arguments for the operation
* @returns void (calls resolve with result)
*/
promise.rawDispatch(resolve, op, args);
/**
* Generic operation dispatch on values (deprecated)
* @param value - Value to operate on
* @param op - Operation name
* @param operands - Operation arguments
* @returns Promise for operation result
*/
function Q.dispatch(value, op, operands);Usage Examples:
const Q = require("q");
// Custom dispatch operations
const objectPromise = Q.resolve({
values: [1, 2, 3, 4, 5],
transform: function(fn) { return this.values.map(fn); },
sum: function() { return this.values.reduce((a, b) => a + b, 0); }
});
// Dispatch custom operations
objectPromise.dispatch("transform", [x => x * 2])
.then(doubled => console.log("Doubled:", doubled)); // [2, 4, 6, 8, 10]
objectPromise.dispatch("sum", [])
.then(sum => console.log("Sum:", sum)); // 15
// Raw dispatch for performance-critical operations
function performRawOperation(promise, operation, args) {
return new Q.Promise((resolve, reject) => {
promise.rawDispatch((result) => {
try {
const operationResult = result[operation].apply(result, args);
resolve(operationResult);
} catch (error) {
reject(error);
}
}, operation, args);
});
}
// Using Q.dispatch (deprecated but still functional)
Q.dispatch({ name: "John" }, "get", ["name"])
.then(name => console.log("Name:", name));
// Advanced dispatch patterns
class PromiseDispatcher {
constructor(promise) {
this.promise = promise;
}
dispatchOperation(op, ...args) {
return this.promise.dispatch(op, args);
}
dispatchMultiple(operations) {
const dispatches = operations.map(({ op, args }) =>
this.promise.dispatch(op, args)
);
return Q.all(dispatches);
}
}
// Usage
const dispatcher = new PromiseDispatcher(objectPromise);
dispatcher.dispatchMultiple([
{ op: "sum", args: [] },
{ op: "transform", args: [x => x + 1] }
]).then(results => {
console.log("Dispatch results:", results);
});System for marking values and promises for pass-by-copy serialization behavior.
/**
* Marks value for pass-by-copy semantics
* @param value - Value to mark for pass-by-copy
* @returns Value marked for pass-by-copy
*/
function Q.passByCopy(value);
// Alias: Q.push(value)
/**
* Checks if value is marked for pass-by-copy
* @param value - Value to check
* @returns True if value is marked for pass-by-copy
*/
function Q.isPortable(value);
/**
* Marks promise for pass-by-copy semantics
* @returns Promise marked for pass-by-copy
*/
promise.pass();
/**
* Checks if promise is marked for pass-by-copy
* @returns True if promise is marked for pass-by-copy
*/
promise.toBePassed();
/**
* Creates pass-by-copy snapshot of fulfilled object
* @returns Promise for serializable snapshot
*/
promise.pull();Usage Examples:
const Q = require("q");
// Mark values for pass-by-copy
const portableData = Q.passByCopy({
name: "John",
age: 30,
preferences: { theme: "dark" }
});
console.log(Q.isPortable(portableData)); // true
// Mark promises for pass-by-copy
const userPromise = fetchUser(123).pass();
console.log(userPromise.toBePassed()); // true
// Create serializable snapshots
const complexObjectPromise = Q.resolve({
id: 1,
data: new Map([["key1", "value1"], ["key2", "value2"]]),
timestamp: new Date(),
process: () => "cannot be serialized"
});
complexObjectPromise.pull()
.then(snapshot => {
console.log("Serializable snapshot:", snapshot);
// Contains only serializable properties
});
// Distributed computing example
function createDistributableTask(data) {
const portableData = Q.passByCopy(data);
return Q.resolve(portableData)
.pass() // Mark promise as portable
.then(data => {
// This promise can be serialized and sent to remote workers
return processOnRemoteWorker(data);
});
}
// Serialization utility
function serializePromiseChain(promise) {
if (promise.toBePassed()) {
return promise.pull().then(data => ({
type: "serialized_promise",
data: JSON.stringify(data),
portable: true
}));
} else {
throw new Error("Promise is not marked for serialization");
}
}
// Remote execution pattern
function executeRemoteley(localPromise) {
return localPromise
.pass()
.pull()
.then(serializableData => {
return sendToRemoteWorker(serializableData);
})
.then(remoteResult => {
return Q.passByCopy(remoteResult);
});
}System for tracking and observing promise completion time estimates.
/**
* Observes changes to completion time estimates
* @param emit - Callback for estimate changes
* @returns Promise with estimate observation
*/
promise.observeEstimate(emit);
/**
* Gets current completion time estimate
* @returns Current estimate in milliseconds
*/
promise.getEstimate();
/**
* Sets completion time estimate on deferred
* @param estimate - Estimate in milliseconds
* @returns void
*/
deferred.setEstimate(estimate);Usage Examples:
const Q = require("q");
// Set estimates on deferred objects
const deferred = Q.defer();
deferred.setEstimate(5000); // Estimate 5 seconds
// Monitor estimate changes
deferred.promise.observeEstimate((estimate) => {
console.log(`Estimated completion in: ${estimate}ms`);
});
// Simulate work with estimate updates
setTimeout(() => {
deferred.setEstimate(3000); // Update to 3 seconds
}, 1000);
setTimeout(() => {
deferred.setEstimate(1000); // Update to 1 second
}, 2000);
setTimeout(() => {
deferred.resolve("Task completed");
}, 3000);
// Get current estimates
console.log("Initial estimate:", deferred.promise.getEstimate());
// Progress tracking utility
class ProgressTracker {
constructor(promise, name) {
this.promise = promise;
this.name = name;
this.startTime = Date.now();
this.setupEstimateObserver();
}
setupEstimateObserver() {
this.promise.observeEstimate((estimate) => {
const elapsed = Date.now() - this.startTime;
const remaining = Math.max(0, estimate - elapsed);
console.log(`${this.name}: ${remaining}ms remaining (${elapsed}ms elapsed)`);
if (remaining > 0) {
const percentage = (elapsed / estimate) * 100;
this.updateProgressBar(Math.min(100, percentage));
}
});
}
updateProgressBar(percentage) {
const bar = "█".repeat(Math.floor(percentage / 5)) +
"░".repeat(20 - Math.floor(percentage / 5));
console.log(`${this.name}: [${bar}] ${percentage.toFixed(1)}%`);
}
}
// Usage
function longRunningTask() {
const deferred = Q.defer();
deferred.setEstimate(10000); // 10 seconds
let progress = 0;
const timer = setInterval(() => {
progress += 1000;
deferred.setEstimate(10000 - progress);
if (progress >= 10000) {
clearInterval(timer);
deferred.resolve("Task completed");
}
}, 1000);
return deferred.promise;
}
const tracker = new ProgressTracker(longRunningTask(), "Data Processing");Support for creating iterators from promised iterable values.
/**
* Creates iterator for fulfilled iterable value
* @returns Promise for iterator object
*/
promise.iterate();Usage Examples:
const Q = require("q");
// Create iterator from promised array
const arrayPromise = Q.resolve([1, 2, 3, 4, 5]);
arrayPromise.iterate()
.then(iterator => {
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
});
// Async iteration utility
function asyncIterate(iterablePromise, processor) {
return iterablePromise.iterate().then(iterator => {
const results = [];
function processNext() {
const { value, done } = iterator.next();
if (done) {
return results;
}
return Q.resolve(processor(value))
.then(processedValue => {
results.push(processedValue);
return processNext();
});
}
return processNext();
});
}
// Usage
const numbersPromise = Q.resolve([1, 2, 3, 4, 5]);
asyncIterate(numbersPromise, num => Q.delay(num * 2, 100))
.then(results => console.log("Processed results:", results));
// Stream processing with iterators
function streamProcess(dataPromise, batchSize = 3) {
return dataPromise.iterate().then(iterator => {
const batches = [];
let currentBatch = [];
function processBatch() {
const { value, done } = iterator.next();
if (done) {
if (currentBatch.length > 0) {
batches.push(currentBatch);
}
return batches;
}
currentBatch.push(value);
if (currentBatch.length >= batchSize) {
batches.push(currentBatch);
currentBatch = [];
}
return processBatch();
}
return processBatch();
});
}
// Usage
const largeDatasetPromise = Q.resolve(Array.from({ length: 10 }, (_, i) => i + 1));
streamProcess(largeDatasetPromise, 3)
.then(batches => {
console.log("Processed in batches:", batches);
// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
});Install with Tessl CLI
npx tessl i tessl/npm-q