function Q(value) { // If the object is already a Promise, return it directly. This enables // the resolve function to both be used to created references from objects, // but to tolerably coerce non-promises to promises. if (value instanceof Promise) { return value; } // assimilate thenables if (isPromiseAlike(value)) { return coerce(value); } else { return fulfill(value); } }
n/a
function promise(resolver) { if (typeof resolver !== "function") { throw new TypeError("resolver must be a function."); } var deferred = defer(); try { resolver(deferred.resolve, deferred.reject, deferred.notify); } catch (reason) { deferred.reject(reason); } return deferred.promise; }
...
This is an alternative promise-creation API that has the same power as
the deferred concept, but without introducing another conceptual entity.
Rewriting the `requestOkText` example above using `Q.Promise`:
```javascript
function requestOkText(url) {
return Q.Promise(function(resolve, reject, notify) {
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.onload = onload;
request.onerror = onerror;
request.onprogress = onprogress;
request.send();
...
function all(promises) { return when(promises, function (promises) { var pendingCount = 0; var deferred = defer(); array_reduce(promises, function (undefined, promise, index) { var snapshot; if ( isPromise(promise) && (snapshot = promise.inspect()).state === "fulfilled" ) { promises[index] = snapshot.value; } else { ++pendingCount; when( promise, function (value) { promises[index] = value; if (--pendingCount === 0) { deferred.resolve(promises); } }, deferred.reject, function (progress) { deferred.notify({ index: index, value: progress }); } ); } }, void 0); if (pendingCount === 0) { deferred.resolve(promises); } return deferred.promise; }); }
...
- Deprecated ``ref`` in favor of ``resolve`` as recommended by
@domenic.
- Update event-queue dependency.
## 0.8.1
- Fixed Opera bug. #35 @cadorn
- Fixed ``Q.all([])`` #32 @domenic
## 0.8.0
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
...
allResolved = function () { if (typeof console !== "undefined" && typeof console.warn === "function") { console.warn(name + " is deprecated, use " + alternative + " instead.", new Error("").stack); } return callback.apply(callback, arguments); }
n/a
function allSettled(promises) { return Q(promises).allSettled(); }
...
};
/**
* @see Promise#allSettled
*/
Q.allSettled = allSettled;
function allSettled(promises) {
return Q(promises).allSettled();
}
/**
* Turns an array of promises into a promise for an array of their states (as
* returned by `inspect`) when they have all settled.
* @param {Array[Any*]} values an array (or promise for an array) of values (or
* promises for values)
...
function any(promises) { if (promises.length === 0) { return Q.resolve(); } var deferred = Q.defer(); var pendingCount = 0; array_reduce(promises, function (prev, current, index) { var promise = promises[index]; pendingCount++; when(promise, onFulfilled, onRejected, onProgress); function onFulfilled(result) { deferred.resolve(result); } function onRejected(err) { pendingCount--; if (pendingCount === 0) { err.message = ("Q can't get fulfillment value from any promise, all " + "promises were rejected. Last error message: " + err.message); deferred.reject(err); } } function onProgress(progress) { deferred.notify({ index: index, value: progress }); } }, undefined); return deferred.promise; }
...
## 1.2.1
- Fix Node.js environment detection for modern Browserify (@kahnjw).
## 1.2.0
- Added Q.any(promisesArray) method (@vergara).
Returns a promise fulfilled with the value of the first resolved promise in
promisesArray. If all promises in promisesArray are rejected, it returns
a rejected promise.
## 1.1.2
- Removed extraneous files from the npm package by using the "files"
...
function async(makeGenerator) { return function () { // when verb is "send", arg is a value // when verb is "throw", arg is an exception function continuer(verb, arg) { var result; // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only // engine that has a deployed base of browsers that support generators. // However, SM's generators use the Python-inspired semantics of // outdated ES6 drafts. We would like to support ES6, but we'd also // like to make it possible to use generators in deployed browsers, so // we also support Python-style generators. At some point we can remove // this block. if (typeof StopIteration === "undefined") { // ES6 Generators try { result = generator[verb](arg); } catch (exception) { return reject(exception); } if (result.done) { return Q(result.value); } else { return when(result.value, callback, errback); } } else { // SpiderMonkey Generators // FIXME: Remove this case when SM does ES6 generators. try { result = generator[verb](arg); } catch (exception) { if (isStopIteration(exception)) { return Q(exception.value); } else { return reject(exception); } } return when(result, callback, errback); } } var generator = makeGenerator.apply(this, arguments); var callback = continuer.bind(continuer, "next"); var errback = continuer.bind(continuer, "throw"); return callback(); }; }
...
* calls the generator and also ends the promise chain, so that any
* unhandled errors are thrown instead of forwarded to the error
* handler. This is useful because it's extremely common to run
* generators at the top-level to work with libraries.
*/
Q.spawn = spawn;
function spawn(makeGenerator) {
Q.done(Q.async(makeGenerator)());
}
// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
/**
* Throws a ReturnValue exception to stop an asynchronous generator.
*
* This interface is a stop-gap measure to support generator return
...
catch = function (object, rejected) { return Q(object).then(void 0, rejected); }
...
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
})
.done();
```
With this approach, you also get implicit error propagation, just like `try`,
`catch`, and `finally`. An error in `promisedStep1` will flow all the way to
...
function defer() { // if "messages" is an "Array", that indicates that the promise has not yet // been resolved. If it is "undefined", it has been resolved. Each // element of the messages array is itself an array of complete arguments to // forward to the resolved promise. We coerce the resolution value to a // promise using the `resolve` function because it handles both fully // non-thenable values and other thenables gracefully. var messages = [], progressListeners = [], resolvedPromise; var deferred = object_create(defer.prototype); var promise = object_create(Promise.prototype); promise.promiseDispatch = function (resolve, op, operands) { var args = array_slice(arguments); if (messages) { messages.push(args); if (op === "when" && operands[1]) { // progress operand progressListeners.push(operands[1]); } } else { Q.nextTick(function () { resolvedPromise.promiseDispatch.apply(resolvedPromise, args); }); } }; // XXX deprecated promise.valueOf = function () { if (messages) { return promise; } var nearerValue = nearer(resolvedPromise); if (isPromise(nearerValue)) { resolvedPromise = nearerValue; // shorten chain } return nearerValue; }; promise.inspect = function () { if (!resolvedPromise) { return { state: "pending" }; } return resolvedPromise.inspect(); }; if (Q.longStackSupport && hasStacks) { try { throw new Error(); } catch (e) { // NOTE: don't try to use `Error.captureStackTrace` or transfer the // accessor around; that causes memory leaks as per GH-111. Just // reify the stack trace as a string ASAP. // // At the same time, cut off the first line; it's always just // "[object Promise]\n", as per the `toString`. promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1); promise.stackCounter = longStackCounter++; } } // NOTE: we do the checks for `resolvedPromise` in each method, instead of // consolidating them into `become`, since otherwise we'd create new // promises with the lines `become(whatever(value))`. See e.g. GH-252. function become(newPromise) { resolvedPromise = newPromise; if (Q.longStackSupport && hasStacks) { // Only hold a reference to the new promise if long stacks // are enabled to reduce memory usage promise.source = newPromise; } array_reduce(messages, function (undefined, message) { Q.nextTick(function () { newPromise.promiseDispatch.apply(newPromise, message); }); }, void 0); messages = void 0; progressListeners = void 0; } deferred.promise = promise; deferred.resolve = function (value) { if (resolvedPromise) { return; } become(Q(value)); }; deferred.fulfill = function (value) { if (resolvedPromise) { return; } become(fulfill(value)); }; deferred.reject = function (reason) { if (resolvedPromise) { return; } become(reject(reason)); }; deferred.notify = function (progress) { if (resolvedPromise) { return; } array_reduce(progressListeners, function (undefined, progressListener) { Q.nextTick(function () { progressListener(progress); }); }, void 0); }; return deferred; }
...
Q.any = any;
function any(promises) {
if (promises.length === 0) {
return Q.resolve();
}
var deferred = Q.defer();
var pendingCount = 0;
array_reduce(promises, function (prev, current, index) {
var promise = promises[index];
pendingCount++;
when(promise, onFulfilled, onRejected, onProgress);
...
del = function (object, key) { return Q(object).dispatch("delete", [key]); }
...
promises, so they can be chained.
```
direct manipulation using a promise as a proxy
-------------------------- -------------------------------
value.foo promise.get("foo")
value.foo = value promise.put("foo", value)
delete value.foo promise.del("foo")
value.foo(...args) promise.post("foo", [args])
value.foo(...args) promise.invoke("foo", ...args)
value(...args) promise.fapply([args])
value(...args) promise.fcall(...args)
```
If the promise is a proxy for a remote object, you can shave
...
delay = function (object, timeout) { if (timeout === void 0) { timeout = object; object = void 0; } return Q(object).delay(timeout); }
...
* If the given promise rejects, that is passed immediately.
*/
Q.delay = function (object, timeout) {
if (timeout === void 0) {
timeout = object;
object = void 0;
}
return Q(object).delay(timeout);
};
Promise.prototype.delay = function (timeout) {
return this.then(function (value) {
var deferred = defer();
setTimeout(function () {
deferred.resolve(value);
...
delete = function (object, key) { return Q(object).dispatch("delete", [key]); }
n/a
denodeify = function (callback) { if (callback === undefined) { throw new Error("Q can't wrap an undefined function"); } var baseArgs = array_slice(arguments, 1); return function () { var nodeArgs = baseArgs.concat(array_slice(arguments)); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(callback).fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }; }
...
return Q.ninvoke(redisClient, "get", "user:1:id");
return Q.npost(redisClient, "get", ["user:1:id"]);
```
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
return readFile("foo.txt", "utf-8");
var redisClientGet = Q.nbind(redisClient.get, redisClient);
return redisClientGet("user:1:id");
```
Finally, if you're working with raw deferred objects, there is a
...
function dispatch(object, op, args) { return Q(object).dispatch(op, args); }
...
* @param object* the recipient
* @param op the name of the message operation, e.g., "when",
* @param args further arguments to be forwarded to the operation
* @returns result {Promise} a promise for the result of the operation
*/
Q.dispatch = dispatch;
function dispatch(object, op, args) {
return Q(object).dispatch(op, args);
}
Promise.prototype.dispatch = function (op, args) {
var self = this;
var deferred = defer();
Q.nextTick(function () {
self.promiseDispatch(deferred.resolve, op, args);
...
done = function (object, fulfilled, rejected, progress) { return Q(object).done(fulfilled, rejected, progress); }
...
* calls the generator and also ends the promise chain, so that any
* unhandled errors are thrown instead of forwarded to the error
* handler. This is useful because it's extremely common to run
* generators at the top-level to work with libraries.
*/
Q.spawn = spawn;
function spawn(makeGenerator) {
Q.done(Q.async(makeGenerator)());
}
// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
/**
* Throws a ReturnValue exception to stop an asynchronous generator.
*
* This interface is a stop-gap measure to support generator return
...
fail = function (object, rejected) { return Q(object).then(void 0, rejected); }
...
return Q(callback).nfapply(args);
};
Promise.prototype.nfapply = function (args) {
var deferred = defer();
var nodeArgs = array_slice(args);
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
...
fapply = function (object, args) { return Q(object).dispatch("apply", [void 0, args]); }
...
return Q(callback).nfapply(args);
};
Promise.prototype.nfapply = function (args) {
var deferred = defer();
var nodeArgs = array_slice(args);
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
...
fbind = function (object) { var promise = Q(object); var args = array_slice(arguments, 1); return function fbound() { return promise.dispatch("apply", [ this, args.concat(array_slice(arguments)) ]); }; }
n/a
fcall = function (object) { return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]); }
...
* .tap(console.log)
* .then(...);
*/
Promise.prototype.tap = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall(value).thenResolve(value);
});
};
/**
* Registers an observer on a promise.
*
* Guarantees:
...
fin = function (object, callback) { return Q(object)["finally"](callback); }
...
returned by ``getInputPromise()`` either returns a value or throws an
error. The value returned or error thrown by ``getInputPromise()``
passes directly to ``outputPromise`` unless the final handler fails, and
may be delayed if the final handler returns a promise.
```javascript
var outputPromise = getInputPromise()
.fin(function () {
// close files, database connections, stop servers, conclude tests
});
```
- If the handler returns a value, the value is ignored
- If the handler throws an error, the error passes to ``outputPromise``
- If the handler returns a promise, ``outputPromise`` gets postponed. The
...
finally = function (object, callback) { return Q(object)["finally"](callback); }
n/a
function fulfill(value) { return Promise({ "when": function () { return value; }, "get": function (name) { return value[name]; }, "set": function (name, rhs) { value[name] = rhs; }, "delete": function (name) { delete value[name]; }, "post": function (name, args) { // Mark Miller proposes that post with no name should apply a // promised function. if (name === null || name === void 0) { return value.apply(void 0, args); } else { return value[name].apply(value, args); } }, "apply": function (thisp, args) { return value.apply(thisp, args); }, "keys": function () { return object_keys(value); } }, void 0, function inspect() { return { state: "fulfilled", value: value }; }); }
n/a
get = function (object, key) { return Q(object).dispatch("get", [key]); }
...
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
term ``def`` was too confusing to new users.
- WARNING: ``spy`` removed in favor of ``fin``.
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
- WARNING: Removed the ``Q`` function module.exports alias
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
ways, making it uncallable.
- Revised ``delay`` so that it accepts both ``(value,
timeout)`` and ``(timeout)`` variations based on
arguments length.
...
getUnhandledReasons = function () { // Make a copy so that consumers can't interfere with our internal state. return unhandledReasons.slice(); }
n/a
invoke = function (object, name) { return Q(object).dispatch("post", [name, array_slice(arguments, 2)]); }
...
```
If there is any chance that the promise you receive is not a Q promise
as provided by your library, you should wrap it using a Q function.
You can even use ``Q.invoke`` as a shorthand.
```javascript
return Q.invoke($, 'ajax', ...)
.then(function () {
});
```
### Over the Wire
...
function isFulfilled(object) { return !isPromise(object) || object.inspect().state === "fulfilled"; }
n/a
function isPending(object) { return isPromise(object) && object.inspect().state === "pending"; }
n/a
function isPromise(object) { return object instanceof Promise; }
n/a
function isPromiseAlike(object) { return isObject(object) && typeof object.then === "function"; }
n/a
function isRejected(object) { return isPromise(object) && object.inspect().state === "rejected"; }
n/a
join = function (x, y) { return Q(x).join(y); }
...
if (p.stack && (!error.__minimumStackCounter__ || error.__minimumStackCounter__ > p.stackCounter)) {
object_defineProperty(error, "__minimumStackCounter__", {value: p.stackCounter, configurable: true});
stacks.unshift(p.stack);
}
}
stacks.unshift(error.stack);
var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n
");
var stack = filterStackString(concatedStacks);
object_defineProperty(error, "stack", {value: stack, configurable: true});
}
}
function filterStackString(stackString) {
var lines = stackString.split("\n");
...
keys = function (object) { return Q(object).dispatch("keys", []); }
n/a
function Promise(descriptor, fallback, inspect) { if (fallback === void 0) { fallback = function (op) { return reject(new Error( "Promise does not support operation: " + op )); }; } if (inspect === void 0) { inspect = function () { return {state: "unknown"}; }; } var promise = object_create(Promise.prototype); promise.promiseDispatch = function (resolve, op, args) { var result; try { if (descriptor[op]) { result = descriptor[op].apply(promise, args); } else { result = fallback.call(promise, op, args); } } catch (exception) { result = reject(exception); } if (resolve) { resolve(result); } }; promise.inspect = inspect; // XXX deprecated `valueOf` and `exception` support if (inspect) { var inspected = inspect(); if (inspected.state === "rejected") { promise.exception = inspected.reason; } promise.valueOf = function () { var inspected = inspect(); if (inspected.state === "pending" || inspected.state === "rejected") { return promise; } return inspected.value; }; } return promise; }
n/a
mapply = function (object, name, args) { return Q(object).dispatch("post", [name, args]); }
n/a
function master(object) { return Promise({ "isDef": function () {} }, function fallback(op, args) { return dispatch(object, op, args); }, function () { return Q(object).inspect(); }); }
n/a
mcall = function (object, name) { return Q(object).dispatch("post", [name, array_slice(arguments, 2)]); }
n/a
nbind = function (callback, thisp) { var baseArgs = array_slice(arguments, 2); return function () { var nodeArgs = baseArgs.concat(array_slice(arguments)); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); function bound() { return callback.apply(thisp, arguments); } Q(bound).fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }; }
...
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
return readFile("foo.txt", "utf-8");
var redisClientGet = Q.nbind(redisClient.get, redisClient);
return redisClientGet("user:1:id");
```
Finally, if you're working with raw deferred objects, there is a
`makeNodeResolver` method on deferreds that can be handy:
```javascript
...
function nearer(value) { if (isPromise(value)) { var inspected = value.inspect(); if (inspected.state === "fulfilled") { return inspected.value; } } return value; }
n/a
nextTick = function (task) { tail = tail.next = { task: task, domain: isNodeJS && process.domain, next: null }; if (!flushing) { flushing = true; requestTick(); } }
...
// `setTimeout`. In this case `setImmediate` is preferred because
// it is faster. Browserify's `process.toString()` yields
// "[object Object]", while in a real Node environment
// `process.toString()` yields "[object process]".
isNodeJS = true;
requestTick = function () {
process.nextTick(flush);
};
} else if (typeof setImmediate === "function") {
// In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
if (typeof window !== "undefined") {
requestTick = setImmediate.bind(window, flush);
} else {
...
nfapply = function (callback, args) { return Q(callback).nfapply(args); }
...
});
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided as an array, and returns a promise.
*
* Q.nfapply(FS.readFile, [__filename])
* .then(function (content) {
* })
*
*/
Q.nfapply = function (callback, args) {
return Q(callback).nfapply(args);
};
...
nfbind = function (callback) { if (callback === undefined) { throw new Error("Q can't wrap an undefined function"); } var baseArgs = array_slice(arguments, 1); return function () { var nodeArgs = baseArgs.concat(array_slice(arguments)); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(callback).fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }; }
...
return deferred.promise;
};
/**
* Wraps a NodeJS continuation passing function and returns an equivalent
* version that returns a promise.
* @example
* Q.nfbind(FS.readFile, __filename)("utf-8")
* .then(console.log)
* .done()
*/
Q.nfbind =
Q.denodeify = function (callback /*...args*/) {
if (callback === undefined) {
throw new Error("Q can't wrap an undefined function");
...
nfcall = function (callback) { var args = array_slice(arguments, 1); return Q(callback).nfapply(args); }
...
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
* Q.nfcall(FS.readFile, __filename)
* .then(function (content) {
* })
*
*/
Q.nfcall = function (callback /*...args*/) {
var args = array_slice(arguments, 1);
return Q(callback).nfapply(args);
...
ninvoke = function (object, name) { var nodeArgs = array_slice(arguments, 2); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
...
If you are working with methods, instead of simple functions, you can easily
run in to the usual problems where passing a method to another function—like
`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
use `Function.prototype.bind` or some nice shortcut methods we provide:
```javascript
return Q.ninvoke(redisClient, "get", "user:1:id");
return Q.npost(redisClient, "get", ["user:1:id"]);
```
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
...
nmapply = function (object, name, args) { return Q(object).npost(name, args); }
n/a
nmcall = function (object, name) { var nodeArgs = array_slice(arguments, 2); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
n/a
noConflict = function () { throw new Error("Q.noConflict only works when Q is used as a global"); }
n/a
function nodeify(object, nodeback) { return Q(object).nodeify(nodeback); }
...
* pass a nodeback, they will receive the result promise.
* @param object a result (or a promise for a result)
* @param {Function} nodeback a Node.js-style callback
* @returns either the promise or nothing
*/
Q.nodeify = nodeify;
function nodeify(object, nodeback) {
return Q(object).nodeify(nodeback);
}
Promise.prototype.nodeify = function (nodeback) {
if (nodeback) {
this.then(function (value) {
Q.nextTick(function () {
nodeback(null, value);
...
npost = function (object, name, args) { return Q(object).npost(name, args); }
...
* @param {String} name name of the method of object
* @param {Array} args arguments to pass to the method; the callback
* will be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
Q.nmapply = // XXX As proposed by "Redsandro"
Q.npost = function (object, name, args) {
return Q(object).npost(name, args);
};
Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
Promise.prototype.npost = function (name, args) {
var nodeArgs = array_slice(args || []);
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
...
nsend = function (object, name) { var nodeArgs = array_slice(arguments, 2); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
n/a
passByCopy = function (object) { //freeze(object); //passByCopies.set(object, true); return object; }
n/a
post = function (object, name, args) { return Q(object).dispatch("post", [name, args]); }
...
```
direct manipulation using a promise as a proxy
-------------------------- -------------------------------
value.foo promise.get("foo")
value.foo = value promise.put("foo", value)
delete value.foo promise.del("foo")
value.foo(...args) promise.post("foo", [args])
value.foo(...args) promise.invoke("foo", ...args)
value(...args) promise.fapply([args])
value(...args) promise.fcall(...args)
```
If the promise is a proxy for a remote object, you can shave
round-trips by using these functions instead of ``then``. To take
...
function progress(object, progressed) { return Q(object).then(void 0, void 0, progressed); }
...
promise.
## 0.8.9
- Added ``nend``
- Added preliminary progress notification support, via
``promise.then(onFulfilled, onRejected, onProgress)``,
``promise.progress(onProgress)``, and ``deferred.notify(...progressData)``.
- Made ``put`` and ``del`` return the object acted upon for easier chaining.
#84
- Fixed coercion cycles with cooperating promises. #106
## 0.8.7
- Support [Montage Require](http://github.com/kriskowal/mr)
...
function promise(resolver) { if (typeof resolver !== "function") { throw new TypeError("resolver must be a function."); } var deferred = defer(); try { resolver(deferred.resolve, deferred.reject, deferred.notify); } catch (reason) { deferred.reject(reason); } return deferred.promise; }
...
and the message now includes the duration of the timeout in
miliseconds. This doesn't constitute (in my opinion) a
backward-incompatibility since it is a change of an undocumented and
unspecified public behavior, but if you happened to depend on the
exception being a string, you will need to revise your code.
- Added ``deferred.makeNodeResolver()`` to replace the more cryptic
``deferred.node()`` method.
- Added experimental ``Q.promise(maker(resolve, reject))`` to make a
promise inside a callback, such that thrown exceptions in the
callback are converted and the resolver and rejecter are arguments.
This is a shorthand for making a deferred directly and inspired by
@gozala’s stream constructor pattern and the Microsoft Windows Metro
Promise constructor interface.
- Added experimental ``Q.begin()`` that is intended to kick off chains
of ``.then`` so that each of these can be reordered without having to
...
function promised(callback) { return function () { return spread([this, all(arguments)], function (self, args) { return callback.apply(self, args); }); }; }
...
/**
* The promised function decorator ensures that any promise arguments
* are settled and passed as values (`this` is also settled and passed
* as a value). It will also ensure that the result of a function is
* always a promise.
*
* @example
* var add = Q.promised(function (a, b) {
* return a + b;
* });
* add(Q(a), Q(B));
*
* @param {function} callback The function to decorate
* @returns {function} a function that has been decorated.
*/
...
function race(answerPs) { return promise(function (resolve, reject) { // Switch to this once we can assume at least ES5 // answerPs.forEach(function (answerP) { // Q(answerP).then(resolve, reject); // }); // Use this in the meantime for (var i = 0, len = answerPs.length; i < len; i++) { Q(answerPs[i]).then(resolve, reject); } }); }
n/a
function reject(reason) { var rejection = Promise({ "when": function (rejected) { // note that the error has been handled if (rejected) { untrackRejection(this); } return rejected ? rejected(reason) : this; } }, function fallback() { return this; }, function inspect() { return { state: "rejected", reason: reason }; }); // Note that the reason has not been handled. trackRejection(rejection, reason); return rejection; }
...
* promise.
* @returns a nodeback
*/
defer.prototype.makeNodeResolver = function () {
var self = this;
return function (error, value) {
if (error) {
self.reject(error);
} else if (arguments.length > 2) {
self.resolve(array_slice(arguments, 1));
} else {
self.resolve(value);
}
};
};
...
function resetUnhandledRejections() { unhandledReasons.length = 0; unhandledRejections.length = 0; if (!trackUnhandledRejections) { trackUnhandledRejections = true; } }
n/a
function Q(value) { // If the object is already a Promise, return it directly. This enables // the resolve function to both be used to created references from objects, // but to tolerably coerce non-promises to promises. if (value instanceof Promise) { return value; } // assimilate thenables if (isPromiseAlike(value)) { return coerce(value); } else { return fulfill(value); } }
...
*/
defer.prototype.makeNodeResolver = function () {
var self = this;
return function (error, value) {
if (error) {
self.reject(error);
} else if (arguments.length > 2) {
self.resolve(array_slice(arguments, 1));
} else {
self.resolve(value);
}
};
};
/**
...
function _return(value) { throw new QReturnValue(value); }
...
* var bar = yield getBarPromise();
* return foo + bar;
* })
* // Older SpiderMonkey style
* Q.async(function () {
* var foo = yield getFooPromise();
* var bar = yield getBarPromise();
* Q.return(foo + bar);
* })
*/
Q["return"] = _return;
function _return(value) {
throw new QReturnValue(value);
}
...
send = function (object, name) { return Q(object).dispatch("post", [name, array_slice(arguments, 2)]); }
...
var request = new XMLHttpRequest();
var deferred = Q.defer();
request.open("GET", url, true);
request.onload = onload;
request.onerror = onerror;
request.onprogress = onprogress;
request.send();
function onload() {
if (request.status === 200) {
deferred.resolve(request.responseText);
} else {
deferred.reject(new Error("Status code was " + request.status));
}
...
set = function (object, key, value) { return Q(object).dispatch("set", [key, value]); }
...
promise.resolve = Q; // ES6
// XXX experimental. This method is a way to denote that a local value is
// serializable and should be immediately dispatched to a remote upon request,
// instead of passing a reference.
Q.passByCopy = function (object) {
//freeze(object);
//passByCopies.set(object, true);
return object;
};
Promise.prototype.passByCopy = function () {
//freeze(object);
//passByCopies.set(object, true);
return this;
...
function spawn(makeGenerator) { Q.done(Q.async(makeGenerator)()); }
n/a
function spread(value, fulfilled, rejected) { return Q(value).spread(fulfilled, rejected); }
...
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
term ``def`` was too confusing to new users.
- WARNING: ``spy`` removed in favor of ``fin``.
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
- WARNING: Removed the ``Q`` function module.exports alias
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
ways, making it uncallable.
- Revised ``delay`` so that it accepts both ``(value,
timeout)`` and ``(timeout)`` variations based on
arguments length.
- Added ``ref().spread(cb(...args))``, a variant of
...
stopUnhandledRejectionTracking = function () { resetUnhandledRejections(); trackUnhandledRejections = false; }
n/a
tap = function (promise, callback) { return Q(promise).tap(callback); }
...
}
}]);
return deferred.promise;
};
Q.tap = function (promise, callback) {
return Q(promise).tap(callback);
};
/**
* Works almost like "finally", but not called for rejections.
* Original resolution value is passed through callback unaffected.
* Callback may return a promise that will be awaited for.
* @param {Function} callback
...
thenReject = function (promise, reason) { return Q(promise).thenReject(reason); }
...
};
Promise.prototype.thenReject = function (reason) {
return this.then(function () { throw reason; });
};
Q.thenReject = function (promise, reason) {
return Q(promise).thenReject(reason);
};
/**
* If an object is not a promise, it is as "near" as possible.
* If a promise is rejected, it is as "near" as possible too.
* If it’s a fulfilled promise, the fulfillment value is nearer.
* If it’s a deferred promise and the deferred has been resolved, the
...
thenResolve = function (promise, value) { return Q(promise).thenResolve(value); }
...
* .tap(console.log)
* .then(...);
*/
Promise.prototype.tap = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall(value).thenResolve(value);
});
};
/**
* Registers an observer on a promise.
*
* Guarantees:
...
timeout = function (object, ms, error) { return Q(object).timeout(ms, error); }
...
* @param {Any*} promise
* @param {Number} milliseconds timeout
* @param {Any*} custom error message or Error object (optional)
* @returns a promise for the resolution of the given promise if it is
* fulfilled before the timeout, otherwise rejected.
*/
Q.timeout = function (object, ms, error) {
return Q(object).timeout(ms, error);
};
Promise.prototype.timeout = function (ms, error) {
var deferred = defer();
var timeoutId = setTimeout(function () {
if (!error || "string" === typeof error) {
error = new Error(error || "Timed out after " + ms + " ms");
...
try = function (object) { return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]); }
n/a
function when(value, fulfilled, rejected, progressed) { return Q(value).then(fulfilled, rejected, progressed); }
...
```
This is a simplified implementation of ``Q.timeout``
```javascript
function timeout(promise, ms) {
var deferred = Q.defer();
Q.when(promise, deferred.resolve);
delay(ms).then(function () {
deferred.reject(new Error("Timed out"));
});
return deferred.promise;
}
```
...
function promise(resolver) { if (typeof resolver !== "function") { throw new TypeError("resolver must be a function."); } var deferred = defer(); try { resolver(deferred.resolve, deferred.reject, deferred.notify); } catch (reason) { deferred.reject(reason); } return deferred.promise; }
...
This is an alternative promise-creation API that has the same power as
the deferred concept, but without introducing another conceptual entity.
Rewriting the `requestOkText` example above using `Q.Promise`:
```javascript
function requestOkText(url) {
return Q.Promise(function(resolve, reject, notify) {
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.onload = onload;
request.onerror = onerror;
request.onprogress = onprogress;
request.send();
...
function all(promises) { return when(promises, function (promises) { var pendingCount = 0; var deferred = defer(); array_reduce(promises, function (undefined, promise, index) { var snapshot; if ( isPromise(promise) && (snapshot = promise.inspect()).state === "fulfilled" ) { promises[index] = snapshot.value; } else { ++pendingCount; when( promise, function (value) { promises[index] = value; if (--pendingCount === 0) { deferred.resolve(promises); } }, deferred.reject, function (progress) { deferred.notify({ index: index, value: progress }); } ); } }, void 0); if (pendingCount === 0) { deferred.resolve(promises); } return deferred.promise; }); }
...
- Deprecated ``ref`` in favor of ``resolve`` as recommended by
@domenic.
- Update event-queue dependency.
## 0.8.1
- Fixed Opera bug. #35 @cadorn
- Fixed ``Q.all([])`` #32 @domenic
## 0.8.0
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
...
function race(answerPs) { return promise(function (resolve, reject) { // Switch to this once we can assume at least ES5 // answerPs.forEach(function (answerP) { // Q(answerP).then(resolve, reject); // }); // Use this in the meantime for (var i = 0, len = answerPs.length; i < len; i++) { Q(answerPs[i]).then(resolve, reject); } }); }
n/a
function reject(reason) { var rejection = Promise({ "when": function (rejected) { // note that the error has been handled if (rejected) { untrackRejection(this); } return rejected ? rejected(reason) : this; } }, function fallback() { return this; }, function inspect() { return { state: "rejected", reason: reason }; }); // Note that the reason has not been handled. trackRejection(rejection, reason); return rejection; }
...
* promise.
* @returns a nodeback
*/
defer.prototype.makeNodeResolver = function () {
var self = this;
return function (error, value) {
if (error) {
self.reject(error);
} else if (arguments.length > 2) {
self.resolve(array_slice(arguments, 1));
} else {
self.resolve(value);
}
};
};
...
function Q(value) { // If the object is already a Promise, return it directly. This enables // the resolve function to both be used to created references from objects, // but to tolerably coerce non-promises to promises. if (value instanceof Promise) { return value; } // assimilate thenables if (isPromiseAlike(value)) { return coerce(value); } else { return fulfill(value); } }
...
*/
defer.prototype.makeNodeResolver = function () {
var self = this;
return function (error, value) {
if (error) {
self.reject(error);
} else if (arguments.length > 2) {
self.resolve(array_slice(arguments, 1));
} else {
self.resolve(value);
}
};
};
/**
...
function defer() { // if "messages" is an "Array", that indicates that the promise has not yet // been resolved. If it is "undefined", it has been resolved. Each // element of the messages array is itself an array of complete arguments to // forward to the resolved promise. We coerce the resolution value to a // promise using the `resolve` function because it handles both fully // non-thenable values and other thenables gracefully. var messages = [], progressListeners = [], resolvedPromise; var deferred = object_create(defer.prototype); var promise = object_create(Promise.prototype); promise.promiseDispatch = function (resolve, op, operands) { var args = array_slice(arguments); if (messages) { messages.push(args); if (op === "when" && operands[1]) { // progress operand progressListeners.push(operands[1]); } } else { Q.nextTick(function () { resolvedPromise.promiseDispatch.apply(resolvedPromise, args); }); } }; // XXX deprecated promise.valueOf = function () { if (messages) { return promise; } var nearerValue = nearer(resolvedPromise); if (isPromise(nearerValue)) { resolvedPromise = nearerValue; // shorten chain } return nearerValue; }; promise.inspect = function () { if (!resolvedPromise) { return { state: "pending" }; } return resolvedPromise.inspect(); }; if (Q.longStackSupport && hasStacks) { try { throw new Error(); } catch (e) { // NOTE: don't try to use `Error.captureStackTrace` or transfer the // accessor around; that causes memory leaks as per GH-111. Just // reify the stack trace as a string ASAP. // // At the same time, cut off the first line; it's always just // "[object Promise]\n", as per the `toString`. promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1); promise.stackCounter = longStackCounter++; } } // NOTE: we do the checks for `resolvedPromise` in each method, instead of // consolidating them into `become`, since otherwise we'd create new // promises with the lines `become(whatever(value))`. See e.g. GH-252. function become(newPromise) { resolvedPromise = newPromise; if (Q.longStackSupport && hasStacks) { // Only hold a reference to the new promise if long stacks // are enabled to reduce memory usage promise.source = newPromise; } array_reduce(messages, function (undefined, message) { Q.nextTick(function () { newPromise.promiseDispatch.apply(newPromise, message); }); }, void 0); messages = void 0; progressListeners = void 0; } deferred.promise = promise; deferred.resolve = function (value) { if (resolvedPromise) { return; } become(Q(value)); }; deferred.fulfill = function (value) { if (resolvedPromise) { return; } become(fulfill(value)); }; deferred.reject = function (reason) { if (resolvedPromise) { return; } become(reject(reason)); }; deferred.notify = function (progress) { if (resolvedPromise) { return; } array_reduce(progressListeners, function (undefined, progressListener) { Q.nextTick(function () { progressListener(progress); }); }, void 0); }; return deferred; }
...
Q.any = any;
function any(promises) {
if (promises.length === 0) {
return Q.resolve();
}
var deferred = Q.defer();
var pendingCount = 0;
array_reduce(promises, function (prev, current, index) {
var promise = promises[index];
pendingCount++;
when(promise, onFulfilled, onRejected, onProgress);
...
makeNodeResolver = function () { var self = this; return function (error, value) { if (error) { self.reject(error); } else if (arguments.length > 2) { self.resolve(array_slice(arguments, 1)); } else { self.resolve(value); } }; }
...
- WARNING: ``promise.timeout`` is now rejected with an ``Error`` object
and the message now includes the duration of the timeout in
miliseconds. This doesn't constitute (in my opinion) a
backward-incompatibility since it is a change of an undocumented and
unspecified public behavior, but if you happened to depend on the
exception being a string, you will need to revise your code.
- Added ``deferred.makeNodeResolver()`` to replace the more cryptic
``deferred.node()`` method.
- Added experimental ``Q.promise(maker(resolve, reject))`` to make a
promise inside a callback, such that thrown exceptions in the
callback are converted and the resolver and rejecter are arguments.
This is a shorthand for making a deferred directly and inspired by
@gozala’s stream constructor pattern and the Microsoft Windows Metro
Promise constructor interface.
...
function Promise(descriptor, fallback, inspect) { if (fallback === void 0) { fallback = function (op) { return reject(new Error( "Promise does not support operation: " + op )); }; } if (inspect === void 0) { inspect = function () { return {state: "unknown"}; }; } var promise = object_create(Promise.prototype); promise.promiseDispatch = function (resolve, op, args) { var result; try { if (descriptor[op]) { result = descriptor[op].apply(promise, args); } else { result = fallback.call(promise, op, args); } } catch (exception) { result = reject(exception); } if (resolve) { resolve(result); } }; promise.inspect = inspect; // XXX deprecated `valueOf` and `exception` support if (inspect) { var inspected = inspect(); if (inspected.state === "rejected") { promise.exception = inspected.reason; } promise.valueOf = function () { var inspected = inspect(); if (inspected.state === "pending" || inspected.state === "rejected") { return promise; } return inspected.value; }; } return promise; }
n/a
all = function () { return all(this); }
...
- Deprecated ``ref`` in favor of ``resolve`` as recommended by
@domenic.
- Update event-queue dependency.
## 0.8.1
- Fixed Opera bug. #35 @cadorn
- Fixed ``Q.all([])`` #32 @domenic
## 0.8.0
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
...
allResolved = function () { return allResolved(this); }
n/a
allSettled = function () { return this.then(function (promises) { return all(array_map(promises, function (promise) { promise = Q(promise); function regardless() { return promise.inspect(); } return promise.then(regardless, regardless); })); }); }
...
};
/**
* @see Promise#allSettled
*/
Q.allSettled = allSettled;
function allSettled(promises) {
return Q(promises).allSettled();
}
/**
* Turns an array of promises into a promise for an array of their states (as
* returned by `inspect`) when they have all settled.
* @param {Array[Any*]} values an array (or promise for an array) of values (or
* promises for values)
...
any = function () { return any(this); }
...
## 1.2.1
- Fix Node.js environment detection for modern Browserify (@kahnjw).
## 1.2.0
- Added Q.any(promisesArray) method (@vergara).
Returns a promise fulfilled with the value of the first resolved promise in
promisesArray. If all promises in promisesArray are rejected, it returns
a rejected promise.
## 1.1.2
- Removed extraneous files from the npm package by using the "files"
...
catch = function (rejected) { return this.then(void 0, rejected); }
...
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
})
.done();
```
With this approach, you also get implicit error propagation, just like `try`,
`catch`, and `finally`. An error in `promisedStep1` will flow all the way to
...
del = function (key) { return this.dispatch("delete", [key]); }
...
promises, so they can be chained.
```
direct manipulation using a promise as a proxy
-------------------------- -------------------------------
value.foo promise.get("foo")
value.foo = value promise.put("foo", value)
delete value.foo promise.del("foo")
value.foo(...args) promise.post("foo", [args])
value.foo(...args) promise.invoke("foo", ...args)
value(...args) promise.fapply([args])
value(...args) promise.fcall(...args)
```
If the promise is a proxy for a remote object, you can shave
...
delay = function (timeout) { return this.then(function (value) { var deferred = defer(); setTimeout(function () { deferred.resolve(value); }, timeout); return deferred.promise; }); }
...
* If the given promise rejects, that is passed immediately.
*/
Q.delay = function (object, timeout) {
if (timeout === void 0) {
timeout = object;
object = void 0;
}
return Q(object).delay(timeout);
};
Promise.prototype.delay = function (timeout) {
return this.then(function (value) {
var deferred = defer();
setTimeout(function () {
deferred.resolve(value);
...
delete = function (key) { return this.dispatch("delete", [key]); }
n/a
denodeify = function () { var args = array_slice(arguments); args.unshift(this); return Q.denodeify.apply(void 0, args); }
...
return Q.ninvoke(redisClient, "get", "user:1:id");
return Q.npost(redisClient, "get", ["user:1:id"]);
```
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
return readFile("foo.txt", "utf-8");
var redisClientGet = Q.nbind(redisClient.get, redisClient);
return redisClientGet("user:1:id");
```
Finally, if you're working with raw deferred objects, there is a
...
dispatch = function (op, args) { var self = this; var deferred = defer(); Q.nextTick(function () { self.promiseDispatch(deferred.resolve, op, args); }); return deferred.promise; }
...
* @param object* the recipient
* @param op the name of the message operation, e.g., "when",
* @param args further arguments to be forwarded to the operation
* @returns result {Promise} a promise for the result of the operation
*/
Q.dispatch = dispatch;
function dispatch(object, op, args) {
return Q(object).dispatch(op, args);
}
Promise.prototype.dispatch = function (op, args) {
var self = this;
var deferred = defer();
Q.nextTick(function () {
self.promiseDispatch(deferred.resolve, op, args);
...
done = function (fulfilled, rejected, progress) { var onUnhandledError = function (error) { // forward to a future turn so that ``when`` // does not catch it and turn it into a rejection. Q.nextTick(function () { makeStackTraceLong(error, promise); if (Q.onerror) { Q.onerror(error); } else { throw error; } }); }; // Avoid unnecessary `nextTick`ing via an unnecessary `when`. var promise = fulfilled || rejected || progress ? this.then(fulfilled, rejected, progress) : this; if (typeof process === "object" && process && process.domain) { onUnhandledError = process.domain.bind(onUnhandledError); } promise.then(void 0, onUnhandledError); }
...
* calls the generator and also ends the promise chain, so that any
* unhandled errors are thrown instead of forwarded to the error
* handler. This is useful because it's extremely common to run
* generators at the top-level to work with libraries.
*/
Q.spawn = spawn;
function spawn(makeGenerator) {
Q.done(Q.async(makeGenerator)());
}
// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
/**
* Throws a ReturnValue exception to stop an asynchronous generator.
*
* This interface is a stop-gap measure to support generator return
...
fail = function (rejected) { return this.then(void 0, rejected); }
...
return Q(callback).nfapply(args);
};
Promise.prototype.nfapply = function (args) {
var deferred = defer();
var nodeArgs = array_slice(args);
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
...
fapply = function (args) { return this.dispatch("apply", [void 0, args]); }
...
return Q(callback).nfapply(args);
};
Promise.prototype.nfapply = function (args) {
var deferred = defer();
var nodeArgs = array_slice(args);
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
...
fbind = function () { var promise = this; var args = array_slice(arguments); return function fbound() { return promise.dispatch("apply", [ this, args.concat(array_slice(arguments)) ]); }; }
n/a
fcall = function () { return this.dispatch("apply", [void 0, array_slice(arguments)]); }
...
* .tap(console.log)
* .then(...);
*/
Promise.prototype.tap = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall(value).thenResolve(value);
});
};
/**
* Registers an observer on a promise.
*
* Guarantees:
...
fin = function (callback) { if (!callback || typeof callback.apply !== "function") { throw new Error("Q can't apply finally callback"); } callback = Q(callback); return this.then(function (value) { return callback.fcall().then(function () { return value; }); }, function (reason) { // TODO attempt to recycle the rejection with "this". return callback.fcall().then(function () { throw reason; }); }); }
...
returned by ``getInputPromise()`` either returns a value or throws an
error. The value returned or error thrown by ``getInputPromise()``
passes directly to ``outputPromise`` unless the final handler fails, and
may be delayed if the final handler returns a promise.
```javascript
var outputPromise = getInputPromise()
.fin(function () {
// close files, database connections, stop servers, conclude tests
});
```
- If the handler returns a value, the value is ignored
- If the handler throws an error, the error passes to ``outputPromise``
- If the handler returns a promise, ``outputPromise`` gets postponed. The
...
finally = function (callback) { if (!callback || typeof callback.apply !== "function") { throw new Error("Q can't apply finally callback"); } callback = Q(callback); return this.then(function (value) { return callback.fcall().then(function () { return value; }); }, function (reason) { // TODO attempt to recycle the rejection with "this". return callback.fcall().then(function () { throw reason; }); }); }
n/a
get = function (key) { return this.dispatch("get", [key]); }
...
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
term ``def`` was too confusing to new users.
- WARNING: ``spy`` removed in favor of ``fin``.
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
- WARNING: Removed the ``Q`` function module.exports alias
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
ways, making it uncallable.
- Revised ``delay`` so that it accepts both ``(value,
timeout)`` and ``(timeout)`` variations based on
arguments length.
...
invoke = function (name) { return this.dispatch("post", [name, array_slice(arguments, 1)]); }
...
```
If there is any chance that the promise you receive is not a Q promise
as provided by your library, you should wrap it using a Q function.
You can even use ``Q.invoke`` as a shorthand.
```javascript
return Q.invoke($, 'ajax', ...)
.then(function () {
});
```
### Over the Wire
...
isFulfilled = function () { return this.inspect().state === "fulfilled"; }
n/a
isPending = function () { return this.inspect().state === "pending"; }
n/a
isRejected = function () { return this.inspect().state === "rejected"; }
n/a
join = function (that) { return Q([this, that]).spread(function (x, y) { if (x === y) { // TODO: "===" should be Object.is or equiv return x; } else { throw new Error("Q can't join: not the same: " + x + " " + y); } }); }
...
if (p.stack && (!error.__minimumStackCounter__ || error.__minimumStackCounter__ > p.stackCounter)) {
object_defineProperty(error, "__minimumStackCounter__", {value: p.stackCounter, configurable: true});
stacks.unshift(p.stack);
}
}
stacks.unshift(error.stack);
var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n
");
var stack = filterStackString(concatedStacks);
object_defineProperty(error, "stack", {value: stack, configurable: true});
}
}
function filterStackString(stackString) {
var lines = stackString.split("\n");
...
keys = function () { return this.dispatch("keys", []); }
n/a
mapply = function (name, args) { return this.dispatch("post", [name, args]); }
n/a
mcall = function (name) { return this.dispatch("post", [name, array_slice(arguments, 1)]); }
n/a
nbind = function () { var args = array_slice(arguments, 0); args.unshift(this); return Q.nbind.apply(void 0, args); }
...
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
return readFile("foo.txt", "utf-8");
var redisClientGet = Q.nbind(redisClient.get, redisClient);
return redisClientGet("user:1:id");
```
Finally, if you're working with raw deferred objects, there is a
`makeNodeResolver` method on deferreds that can be handy:
```javascript
...
nfapply = function (args) { var deferred = defer(); var nodeArgs = array_slice(args); nodeArgs.push(deferred.makeNodeResolver()); this.fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }
...
});
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided as an array, and returns a promise.
*
* Q.nfapply(FS.readFile, [__filename])
* .then(function (content) {
* })
*
*/
Q.nfapply = function (callback, args) {
return Q(callback).nfapply(args);
};
...
nfbind = function () { var args = array_slice(arguments); args.unshift(this); return Q.denodeify.apply(void 0, args); }
...
return deferred.promise;
};
/**
* Wraps a NodeJS continuation passing function and returns an equivalent
* version that returns a promise.
* @example
* Q.nfbind(FS.readFile, __filename)("utf-8")
* .then(console.log)
* .done()
*/
Q.nfbind =
Q.denodeify = function (callback /*...args*/) {
if (callback === undefined) {
throw new Error("Q can't wrap an undefined function");
...
nfcall = function () { var nodeArgs = array_slice(arguments); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); this.fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }
...
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
* Q.nfcall(FS.readFile, __filename)
* .then(function (content) {
* })
*
*/
Q.nfcall = function (callback /*...args*/) {
var args = array_slice(arguments, 1);
return Q(callback).nfapply(args);
...
ninvoke = function (name) { var nodeArgs = array_slice(arguments, 1); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); this.dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
...
If you are working with methods, instead of simple functions, you can easily
run in to the usual problems where passing a method to another function—like
`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
use `Function.prototype.bind` or some nice shortcut methods we provide:
```javascript
return Q.ninvoke(redisClient, "get", "user:1:id");
return Q.npost(redisClient, "get", ["user:1:id"]);
```
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
...
nmapply = function (name, args) { var nodeArgs = array_slice(args || []); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); this.dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
n/a
nmcall = function (name) { var nodeArgs = array_slice(arguments, 1); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); this.dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
n/a
nodeify = function (nodeback) { if (nodeback) { this.then(function (value) { Q.nextTick(function () { nodeback(null, value); }); }, function (error) { Q.nextTick(function () { nodeback(error); }); }); } else { return this; } }
...
* pass a nodeback, they will receive the result promise.
* @param object a result (or a promise for a result)
* @param {Function} nodeback a Node.js-style callback
* @returns either the promise or nothing
*/
Q.nodeify = nodeify;
function nodeify(object, nodeback) {
return Q(object).nodeify(nodeback);
}
Promise.prototype.nodeify = function (nodeback) {
if (nodeback) {
this.then(function (value) {
Q.nextTick(function () {
nodeback(null, value);
...
npost = function (name, args) { var nodeArgs = array_slice(args || []); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); this.dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
...
* @param {String} name name of the method of object
* @param {Array} args arguments to pass to the method; the callback
* will be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
Q.nmapply = // XXX As proposed by "Redsandro"
Q.npost = function (object, name, args) {
return Q(object).npost(name, args);
};
Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
Promise.prototype.npost = function (name, args) {
var nodeArgs = array_slice(args || []);
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
...
nsend = function (name) { var nodeArgs = array_slice(arguments, 1); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); this.dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
n/a
passByCopy = function () { //freeze(object); //passByCopies.set(object, true); return this; }
n/a
post = function (name, args) { return this.dispatch("post", [name, args]); }
...
```
direct manipulation using a promise as a proxy
-------------------------- -------------------------------
value.foo promise.get("foo")
value.foo = value promise.put("foo", value)
delete value.foo promise.del("foo")
value.foo(...args) promise.post("foo", [args])
value.foo(...args) promise.invoke("foo", ...args)
value(...args) promise.fapply([args])
value(...args) promise.fcall(...args)
```
If the promise is a proxy for a remote object, you can shave
round-trips by using these functions instead of ``then``. To take
...
progress = function (progressed) { return this.then(void 0, void 0, progressed); }
...
promise.
## 0.8.9
- Added ``nend``
- Added preliminary progress notification support, via
``promise.then(onFulfilled, onRejected, onProgress)``,
``promise.progress(onProgress)``, and ``deferred.notify(...progressData)``.
- Made ``put`` and ``del`` return the object acted upon for easier chaining.
#84
- Fixed coercion cycles with cooperating promises. #106
## 0.8.7
- Support [Montage Require](http://github.com/kriskowal/mr)
...
race = function () { return this.then(Q.race); }
n/a
send = function (name) { return this.dispatch("post", [name, array_slice(arguments, 1)]); }
...
var request = new XMLHttpRequest();
var deferred = Q.defer();
request.open("GET", url, true);
request.onload = onload;
request.onerror = onerror;
request.onprogress = onprogress;
request.send();
function onload() {
if (request.status === 200) {
deferred.resolve(request.responseText);
} else {
deferred.reject(new Error("Status code was " + request.status));
}
...
set = function (key, value) { return this.dispatch("set", [key, value]); }
...
promise.resolve = Q; // ES6
// XXX experimental. This method is a way to denote that a local value is
// serializable and should be immediately dispatched to a remote upon request,
// instead of passing a reference.
Q.passByCopy = function (object) {
//freeze(object);
//passByCopies.set(object, true);
return object;
};
Promise.prototype.passByCopy = function () {
//freeze(object);
//passByCopies.set(object, true);
return this;
...
spread = function (fulfilled, rejected) { return this.all().then(function (array) { return fulfilled.apply(void 0, array); }, rejected); }
...
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
term ``def`` was too confusing to new users.
- WARNING: ``spy`` removed in favor of ``fin``.
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
- WARNING: Removed the ``Q`` function module.exports alias
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
ways, making it uncallable.
- Revised ``delay`` so that it accepts both ``(value,
timeout)`` and ``(timeout)`` variations based on
arguments length.
- Added ``ref().spread(cb(...args))``, a variant of
...
tap = function (callback) { callback = Q(callback); return this.then(function (value) { return callback.fcall(value).thenResolve(value); }); }
...
}
}]);
return deferred.promise;
};
Q.tap = function (promise, callback) {
return Q(promise).tap(callback);
};
/**
* Works almost like "finally", but not called for rejections.
* Original resolution value is passed through callback unaffected.
* Callback may return a promise that will be awaited for.
* @param {Function} callback
...
then = function (fulfilled, rejected, progressed) { var self = this; var deferred = defer(); var done = false; // ensure the untrusted promise makes at most a // single call to one of the callbacks function _fulfilled(value) { try { return typeof fulfilled === "function" ? fulfilled(value) : value; } catch (exception) { return reject(exception); } } function _rejected(exception) { if (typeof rejected === "function") { makeStackTraceLong(exception, self); try { return rejected(exception); } catch (newException) { return reject(newException); } } return reject(exception); } function _progressed(value) { return typeof progressed === "function" ? progressed(value) : value; } Q.nextTick(function () { self.promiseDispatch(function (value) { if (done) { return; } done = true; deferred.resolve(_fulfilled(value)); }, "when", [function (exception) { if (done) { return; } done = true; deferred.resolve(_rejected(exception)); }]); }); // Progress propagator need to be attached in the current tick. self.promiseDispatch(void 0, "when", [void 0, function (value) { var newValue; var threw = false; try { newValue = _progressed(value); } catch (e) { threw = true; if (Q.onerror) { Q.onerror(e); } else { throw e; } } if (!threw) { deferred.notify(newValue); } }]); return deferred.promise; }
...
- Fixed ``spread`` not calling the passed rejection handler if given a rejected
promise.
## 0.8.9
- Added ``nend``
- Added preliminary progress notification support, via
``promise.then(onFulfilled, onRejected, onProgress)``,
``promise.progress(onProgress)``, and ``deferred.notify(...progressData)``.
- Made ``put`` and ``del`` return the object acted upon for easier chaining.
#84
- Fixed coercion cycles with cooperating promises. #106
## 0.8.7
...
thenReject = function (reason) { return this.then(function () { throw reason; }); }
...
};
Promise.prototype.thenReject = function (reason) {
return this.then(function () { throw reason; });
};
Q.thenReject = function (promise, reason) {
return Q(promise).thenReject(reason);
};
/**
* If an object is not a promise, it is as "near" as possible.
* If a promise is rejected, it is as "near" as possible too.
* If it’s a fulfilled promise, the fulfillment value is nearer.
* If it’s a deferred promise and the deferred has been resolved, the
...
thenResolve = function (value) { return this.then(function () { return value; }); }
...
* .tap(console.log)
* .then(...);
*/
Promise.prototype.tap = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall(value).thenResolve(value);
});
};
/**
* Registers an observer on a promise.
*
* Guarantees:
...
timeout = function (ms, error) { var deferred = defer(); var timeoutId = setTimeout(function () { if (!error || "string" === typeof error) { error = new Error(error || "Timed out after " + ms + " ms"); error.code = "ETIMEDOUT"; } deferred.reject(error); }, ms); this.then(function (value) { clearTimeout(timeoutId); deferred.resolve(value); }, function (exception) { clearTimeout(timeoutId); deferred.reject(exception); }, deferred.notify); return deferred.promise; }
...
* @param {Any*} promise
* @param {Number} milliseconds timeout
* @param {Any*} custom error message or Error object (optional)
* @returns a promise for the resolution of the given promise if it is
* fulfilled before the timeout, otherwise rejected.
*/
Q.timeout = function (object, ms, error) {
return Q(object).timeout(ms, error);
};
Promise.prototype.timeout = function (ms, error) {
var deferred = defer();
var timeoutId = setTimeout(function () {
if (!error || "string" === typeof error) {
error = new Error(error || "Timed out after " + ms + " ms");
...
toString = function () { return "[object Promise]"; }
...
if (!flushing) {
flushing = true;
requestTick();
}
};
if (typeof process === "object" &&
process.toString() === "[object process]" && process.nextTick
) {
// Ensure Q is in a real Node environment, with a `process.nextTick`.
// To see through fake Node environments:
// * Mocha test runner - exposes a `process` global without a `nextTick`
// * Browserify - exposes a `process.nexTick` function that uses
// `setTimeout`. In this case `setImmediate` is preferred because
// it is faster. Browserify's `process.toString()` yields
// "[object Object]", while in a real Node environment
...
nextTick = function (task) { tail = tail.next = { task: task, domain: isNodeJS && process.domain, next: null }; if (!flushing) { flushing = true; requestTick(); } }
...
// `setTimeout`. In this case `setImmediate` is preferred because
// it is faster. Browserify's `process.toString()` yields
// "[object Object]", while in a real Node environment
// `process.toString()` yields "[object process]".
isNodeJS = true;
requestTick = function () {
process.nextTick(flush);
};
} else if (typeof setImmediate === "function") {
// In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
if (typeof window !== "undefined") {
requestTick = setImmediate.bind(window, flush);
} else {
...
runAfter = function (task) { laterQueue.push(task); if (!flushing) { flushing = true; requestTick(); } }
...
}
function trackRejection(promise, reason) {
if (!trackUnhandledRejections) {
return;
}
if (typeof process === "object" && typeof process.emit === "function") {
Q.nextTick.runAfter(function () {
if (array_indexOf(unhandledRejections, promise) !== -1) {
process.emit("unhandledRejection", reason, promise);
reportedUnhandledRejections.push(promise);
}
});
}
...
function Q(value) { // If the object is already a Promise, return it directly. This enables // the resolve function to both be used to created references from objects, // but to tolerably coerce non-promises to promises. if (value instanceof Promise) { return value; } // assimilate thenables if (isPromiseAlike(value)) { return coerce(value); } else { return fulfill(value); } }
...
*/
defer.prototype.makeNodeResolver = function () {
var self = this;
return function (error, value) {
if (error) {
self.reject(error);
} else if (arguments.length > 2) {
self.resolve(array_slice(arguments, 1));
} else {
self.resolve(value);
}
};
};
/**
...
function promise(resolver) { if (typeof resolver !== "function") { throw new TypeError("resolver must be a function."); } var deferred = defer(); try { resolver(deferred.resolve, deferred.reject, deferred.notify); } catch (reason) { deferred.reject(reason); } return deferred.promise; }
...
This is an alternative promise-creation API that has the same power as
the deferred concept, but without introducing another conceptual entity.
Rewriting the `requestOkText` example above using `Q.Promise`:
```javascript
function requestOkText(url) {
return Q.Promise(function(resolve, reject, notify) {
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.onload = onload;
request.onerror = onerror;
request.onprogress = onprogress;
request.send();
...
function all(promises) { return when(promises, function (promises) { var pendingCount = 0; var deferred = defer(); array_reduce(promises, function (undefined, promise, index) { var snapshot; if ( isPromise(promise) && (snapshot = promise.inspect()).state === "fulfilled" ) { promises[index] = snapshot.value; } else { ++pendingCount; when( promise, function (value) { promises[index] = value; if (--pendingCount === 0) { deferred.resolve(promises); } }, deferred.reject, function (progress) { deferred.notify({ index: index, value: progress }); } ); } }, void 0); if (pendingCount === 0) { deferred.resolve(promises); } return deferred.promise; }); }
...
- Deprecated ``ref`` in favor of ``resolve`` as recommended by
@domenic.
- Update event-queue dependency.
## 0.8.1
- Fixed Opera bug. #35 @cadorn
- Fixed ``Q.all([])`` #32 @domenic
## 0.8.0
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
...
allResolved = function () { if (typeof console !== "undefined" && typeof console.warn === "function") { console.warn(name + " is deprecated, use " + alternative + " instead.", new Error("").stack); } return callback.apply(callback, arguments); }
n/a
function allSettled(promises) { return Q(promises).allSettled(); }
...
};
/**
* @see Promise#allSettled
*/
Q.allSettled = allSettled;
function allSettled(promises) {
return Q(promises).allSettled();
}
/**
* Turns an array of promises into a promise for an array of their states (as
* returned by `inspect`) when they have all settled.
* @param {Array[Any*]} values an array (or promise for an array) of values (or
* promises for values)
...
function any(promises) { if (promises.length === 0) { return Q.resolve(); } var deferred = Q.defer(); var pendingCount = 0; array_reduce(promises, function (prev, current, index) { var promise = promises[index]; pendingCount++; when(promise, onFulfilled, onRejected, onProgress); function onFulfilled(result) { deferred.resolve(result); } function onRejected(err) { pendingCount--; if (pendingCount === 0) { err.message = ("Q can't get fulfillment value from any promise, all " + "promises were rejected. Last error message: " + err.message); deferred.reject(err); } } function onProgress(progress) { deferred.notify({ index: index, value: progress }); } }, undefined); return deferred.promise; }
...
## 1.2.1
- Fix Node.js environment detection for modern Browserify (@kahnjw).
## 1.2.0
- Added Q.any(promisesArray) method (@vergara).
Returns a promise fulfilled with the value of the first resolved promise in
promisesArray. If all promises in promisesArray are rejected, it returns
a rejected promise.
## 1.1.2
- Removed extraneous files from the npm package by using the "files"
...
function async(makeGenerator) { return function () { // when verb is "send", arg is a value // when verb is "throw", arg is an exception function continuer(verb, arg) { var result; // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only // engine that has a deployed base of browsers that support generators. // However, SM's generators use the Python-inspired semantics of // outdated ES6 drafts. We would like to support ES6, but we'd also // like to make it possible to use generators in deployed browsers, so // we also support Python-style generators. At some point we can remove // this block. if (typeof StopIteration === "undefined") { // ES6 Generators try { result = generator[verb](arg); } catch (exception) { return reject(exception); } if (result.done) { return Q(result.value); } else { return when(result.value, callback, errback); } } else { // SpiderMonkey Generators // FIXME: Remove this case when SM does ES6 generators. try { result = generator[verb](arg); } catch (exception) { if (isStopIteration(exception)) { return Q(exception.value); } else { return reject(exception); } } return when(result, callback, errback); } } var generator = makeGenerator.apply(this, arguments); var callback = continuer.bind(continuer, "next"); var errback = continuer.bind(continuer, "throw"); return callback(); }; }
...
* calls the generator and also ends the promise chain, so that any
* unhandled errors are thrown instead of forwarded to the error
* handler. This is useful because it's extremely common to run
* generators at the top-level to work with libraries.
*/
Q.spawn = spawn;
function spawn(makeGenerator) {
Q.done(Q.async(makeGenerator)());
}
// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
/**
* Throws a ReturnValue exception to stop an asynchronous generator.
*
* This interface is a stop-gap measure to support generator return
...
catch = function (object, rejected) { return Q(object).then(void 0, rejected); }
...
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
})
.done();
```
With this approach, you also get implicit error propagation, just like `try`,
`catch`, and `finally`. An error in `promisedStep1` will flow all the way to
...
function defer() { // if "messages" is an "Array", that indicates that the promise has not yet // been resolved. If it is "undefined", it has been resolved. Each // element of the messages array is itself an array of complete arguments to // forward to the resolved promise. We coerce the resolution value to a // promise using the `resolve` function because it handles both fully // non-thenable values and other thenables gracefully. var messages = [], progressListeners = [], resolvedPromise; var deferred = object_create(defer.prototype); var promise = object_create(Promise.prototype); promise.promiseDispatch = function (resolve, op, operands) { var args = array_slice(arguments); if (messages) { messages.push(args); if (op === "when" && operands[1]) { // progress operand progressListeners.push(operands[1]); } } else { Q.nextTick(function () { resolvedPromise.promiseDispatch.apply(resolvedPromise, args); }); } }; // XXX deprecated promise.valueOf = function () { if (messages) { return promise; } var nearerValue = nearer(resolvedPromise); if (isPromise(nearerValue)) { resolvedPromise = nearerValue; // shorten chain } return nearerValue; }; promise.inspect = function () { if (!resolvedPromise) { return { state: "pending" }; } return resolvedPromise.inspect(); }; if (Q.longStackSupport && hasStacks) { try { throw new Error(); } catch (e) { // NOTE: don't try to use `Error.captureStackTrace` or transfer the // accessor around; that causes memory leaks as per GH-111. Just // reify the stack trace as a string ASAP. // // At the same time, cut off the first line; it's always just // "[object Promise]\n", as per the `toString`. promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1); promise.stackCounter = longStackCounter++; } } // NOTE: we do the checks for `resolvedPromise` in each method, instead of // consolidating them into `become`, since otherwise we'd create new // promises with the lines `become(whatever(value))`. See e.g. GH-252. function become(newPromise) { resolvedPromise = newPromise; if (Q.longStackSupport && hasStacks) { // Only hold a reference to the new promise if long stacks // are enabled to reduce memory usage promise.source = newPromise; } array_reduce(messages, function (undefined, message) { Q.nextTick(function () { newPromise.promiseDispatch.apply(newPromise, message); }); }, void 0); messages = void 0; progressListeners = void 0; } deferred.promise = promise; deferred.resolve = function (value) { if (resolvedPromise) { return; } become(Q(value)); }; deferred.fulfill = function (value) { if (resolvedPromise) { return; } become(fulfill(value)); }; deferred.reject = function (reason) { if (resolvedPromise) { return; } become(reject(reason)); }; deferred.notify = function (progress) { if (resolvedPromise) { return; } array_reduce(progressListeners, function (undefined, progressListener) { Q.nextTick(function () { progressListener(progress); }); }, void 0); }; return deferred; }
...
Q.any = any;
function any(promises) {
if (promises.length === 0) {
return Q.resolve();
}
var deferred = Q.defer();
var pendingCount = 0;
array_reduce(promises, function (prev, current, index) {
var promise = promises[index];
pendingCount++;
when(promise, onFulfilled, onRejected, onProgress);
...
del = function (object, key) { return Q(object).dispatch("delete", [key]); }
...
promises, so they can be chained.
```
direct manipulation using a promise as a proxy
-------------------------- -------------------------------
value.foo promise.get("foo")
value.foo = value promise.put("foo", value)
delete value.foo promise.del("foo")
value.foo(...args) promise.post("foo", [args])
value.foo(...args) promise.invoke("foo", ...args)
value(...args) promise.fapply([args])
value(...args) promise.fcall(...args)
```
If the promise is a proxy for a remote object, you can shave
...
delay = function (object, timeout) { if (timeout === void 0) { timeout = object; object = void 0; } return Q(object).delay(timeout); }
...
* If the given promise rejects, that is passed immediately.
*/
Q.delay = function (object, timeout) {
if (timeout === void 0) {
timeout = object;
object = void 0;
}
return Q(object).delay(timeout);
};
Promise.prototype.delay = function (timeout) {
return this.then(function (value) {
var deferred = defer();
setTimeout(function () {
deferred.resolve(value);
...
delete = function (object, key) { return Q(object).dispatch("delete", [key]); }
n/a
denodeify = function (callback) { if (callback === undefined) { throw new Error("Q can't wrap an undefined function"); } var baseArgs = array_slice(arguments, 1); return function () { var nodeArgs = baseArgs.concat(array_slice(arguments)); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(callback).fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }; }
...
return Q.ninvoke(redisClient, "get", "user:1:id");
return Q.npost(redisClient, "get", ["user:1:id"]);
```
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
return readFile("foo.txt", "utf-8");
var redisClientGet = Q.nbind(redisClient.get, redisClient);
return redisClientGet("user:1:id");
```
Finally, if you're working with raw deferred objects, there is a
...
function dispatch(object, op, args) { return Q(object).dispatch(op, args); }
...
* @param object* the recipient
* @param op the name of the message operation, e.g., "when",
* @param args further arguments to be forwarded to the operation
* @returns result {Promise} a promise for the result of the operation
*/
Q.dispatch = dispatch;
function dispatch(object, op, args) {
return Q(object).dispatch(op, args);
}
Promise.prototype.dispatch = function (op, args) {
var self = this;
var deferred = defer();
Q.nextTick(function () {
self.promiseDispatch(deferred.resolve, op, args);
...
done = function (object, fulfilled, rejected, progress) { return Q(object).done(fulfilled, rejected, progress); }
...
* calls the generator and also ends the promise chain, so that any
* unhandled errors are thrown instead of forwarded to the error
* handler. This is useful because it's extremely common to run
* generators at the top-level to work with libraries.
*/
Q.spawn = spawn;
function spawn(makeGenerator) {
Q.done(Q.async(makeGenerator)());
}
// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
/**
* Throws a ReturnValue exception to stop an asynchronous generator.
*
* This interface is a stop-gap measure to support generator return
...
fail = function (object, rejected) { return Q(object).then(void 0, rejected); }
...
return Q(callback).nfapply(args);
};
Promise.prototype.nfapply = function (args) {
var deferred = defer();
var nodeArgs = array_slice(args);
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
...
fapply = function (object, args) { return Q(object).dispatch("apply", [void 0, args]); }
...
return Q(callback).nfapply(args);
};
Promise.prototype.nfapply = function (args) {
var deferred = defer();
var nodeArgs = array_slice(args);
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
...
fbind = function (object) { var promise = Q(object); var args = array_slice(arguments, 1); return function fbound() { return promise.dispatch("apply", [ this, args.concat(array_slice(arguments)) ]); }; }
n/a
fcall = function (object) { return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]); }
...
* .tap(console.log)
* .then(...);
*/
Promise.prototype.tap = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall(value).thenResolve(value);
});
};
/**
* Registers an observer on a promise.
*
* Guarantees:
...
fin = function (object, callback) { return Q(object)["finally"](callback); }
...
returned by ``getInputPromise()`` either returns a value or throws an
error. The value returned or error thrown by ``getInputPromise()``
passes directly to ``outputPromise`` unless the final handler fails, and
may be delayed if the final handler returns a promise.
```javascript
var outputPromise = getInputPromise()
.fin(function () {
// close files, database connections, stop servers, conclude tests
});
```
- If the handler returns a value, the value is ignored
- If the handler throws an error, the error passes to ``outputPromise``
- If the handler returns a promise, ``outputPromise`` gets postponed. The
...
finally = function (object, callback) { return Q(object)["finally"](callback); }
n/a
function fulfill(value) { return Promise({ "when": function () { return value; }, "get": function (name) { return value[name]; }, "set": function (name, rhs) { value[name] = rhs; }, "delete": function (name) { delete value[name]; }, "post": function (name, args) { // Mark Miller proposes that post with no name should apply a // promised function. if (name === null || name === void 0) { return value.apply(void 0, args); } else { return value[name].apply(value, args); } }, "apply": function (thisp, args) { return value.apply(thisp, args); }, "keys": function () { return object_keys(value); } }, void 0, function inspect() { return { state: "fulfilled", value: value }; }); }
n/a
get = function (object, key) { return Q(object).dispatch("get", [key]); }
...
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
term ``def`` was too confusing to new users.
- WARNING: ``spy`` removed in favor of ``fin``.
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
- WARNING: Removed the ``Q`` function module.exports alias
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
ways, making it uncallable.
- Revised ``delay`` so that it accepts both ``(value,
timeout)`` and ``(timeout)`` variations based on
arguments length.
...
getUnhandledReasons = function () { // Make a copy so that consumers can't interfere with our internal state. return unhandledReasons.slice(); }
n/a
invoke = function (object, name) { return Q(object).dispatch("post", [name, array_slice(arguments, 2)]); }
...
```
If there is any chance that the promise you receive is not a Q promise
as provided by your library, you should wrap it using a Q function.
You can even use ``Q.invoke`` as a shorthand.
```javascript
return Q.invoke($, 'ajax', ...)
.then(function () {
});
```
### Over the Wire
...
function isFulfilled(object) { return !isPromise(object) || object.inspect().state === "fulfilled"; }
n/a
function isPending(object) { return isPromise(object) && object.inspect().state === "pending"; }
n/a
function isPromise(object) { return object instanceof Promise; }
n/a
function isPromiseAlike(object) { return isObject(object) && typeof object.then === "function"; }
n/a
function isRejected(object) { return isPromise(object) && object.inspect().state === "rejected"; }
n/a
join = function (x, y) { return Q(x).join(y); }
...
if (p.stack && (!error.__minimumStackCounter__ || error.__minimumStackCounter__ > p.stackCounter)) {
object_defineProperty(error, "__minimumStackCounter__", {value: p.stackCounter, configurable: true});
stacks.unshift(p.stack);
}
}
stacks.unshift(error.stack);
var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n
");
var stack = filterStackString(concatedStacks);
object_defineProperty(error, "stack", {value: stack, configurable: true});
}
}
function filterStackString(stackString) {
var lines = stackString.split("\n");
...
keys = function (object) { return Q(object).dispatch("keys", []); }
n/a
function Promise(descriptor, fallback, inspect) { if (fallback === void 0) { fallback = function (op) { return reject(new Error( "Promise does not support operation: " + op )); }; } if (inspect === void 0) { inspect = function () { return {state: "unknown"}; }; } var promise = object_create(Promise.prototype); promise.promiseDispatch = function (resolve, op, args) { var result; try { if (descriptor[op]) { result = descriptor[op].apply(promise, args); } else { result = fallback.call(promise, op, args); } } catch (exception) { result = reject(exception); } if (resolve) { resolve(result); } }; promise.inspect = inspect; // XXX deprecated `valueOf` and `exception` support if (inspect) { var inspected = inspect(); if (inspected.state === "rejected") { promise.exception = inspected.reason; } promise.valueOf = function () { var inspected = inspect(); if (inspected.state === "pending" || inspected.state === "rejected") { return promise; } return inspected.value; }; } return promise; }
n/a
mapply = function (object, name, args) { return Q(object).dispatch("post", [name, args]); }
n/a
function master(object) { return Promise({ "isDef": function () {} }, function fallback(op, args) { return dispatch(object, op, args); }, function () { return Q(object).inspect(); }); }
n/a
mcall = function (object, name) { return Q(object).dispatch("post", [name, array_slice(arguments, 2)]); }
n/a
nbind = function (callback, thisp) { var baseArgs = array_slice(arguments, 2); return function () { var nodeArgs = baseArgs.concat(array_slice(arguments)); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); function bound() { return callback.apply(thisp, arguments); } Q(bound).fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }; }
...
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
return readFile("foo.txt", "utf-8");
var redisClientGet = Q.nbind(redisClient.get, redisClient);
return redisClientGet("user:1:id");
```
Finally, if you're working with raw deferred objects, there is a
`makeNodeResolver` method on deferreds that can be handy:
```javascript
...
function nearer(value) { if (isPromise(value)) { var inspected = value.inspect(); if (inspected.state === "fulfilled") { return inspected.value; } } return value; }
n/a
nextTick = function (task) { tail = tail.next = { task: task, domain: isNodeJS && process.domain, next: null }; if (!flushing) { flushing = true; requestTick(); } }
...
// `setTimeout`. In this case `setImmediate` is preferred because
// it is faster. Browserify's `process.toString()` yields
// "[object Object]", while in a real Node environment
// `process.toString()` yields "[object process]".
isNodeJS = true;
requestTick = function () {
process.nextTick(flush);
};
} else if (typeof setImmediate === "function") {
// In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
if (typeof window !== "undefined") {
requestTick = setImmediate.bind(window, flush);
} else {
...
nfapply = function (callback, args) { return Q(callback).nfapply(args); }
...
});
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided as an array, and returns a promise.
*
* Q.nfapply(FS.readFile, [__filename])
* .then(function (content) {
* })
*
*/
Q.nfapply = function (callback, args) {
return Q(callback).nfapply(args);
};
...
nfbind = function (callback) { if (callback === undefined) { throw new Error("Q can't wrap an undefined function"); } var baseArgs = array_slice(arguments, 1); return function () { var nodeArgs = baseArgs.concat(array_slice(arguments)); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(callback).fapply(nodeArgs).fail(deferred.reject); return deferred.promise; }; }
...
return deferred.promise;
};
/**
* Wraps a NodeJS continuation passing function and returns an equivalent
* version that returns a promise.
* @example
* Q.nfbind(FS.readFile, __filename)("utf-8")
* .then(console.log)
* .done()
*/
Q.nfbind =
Q.denodeify = function (callback /*...args*/) {
if (callback === undefined) {
throw new Error("Q can't wrap an undefined function");
...
nfcall = function (callback) { var args = array_slice(arguments, 1); return Q(callback).nfapply(args); }
...
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
* Q.nfcall(FS.readFile, __filename)
* .then(function (content) {
* })
*
*/
Q.nfcall = function (callback /*...args*/) {
var args = array_slice(arguments, 1);
return Q(callback).nfapply(args);
...
ninvoke = function (object, name) { var nodeArgs = array_slice(arguments, 2); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
...
If you are working with methods, instead of simple functions, you can easily
run in to the usual problems where passing a method to another function—like
`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
use `Function.prototype.bind` or some nice shortcut methods we provide:
```javascript
return Q.ninvoke(redisClient, "get", "user:1:id");
return Q.npost(redisClient, "get", ["user:1:id"]);
```
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
```javascript
var readFile = Q.denodeify(FS.readFile);
...
nmapply = function (object, name, args) { return Q(object).npost(name, args); }
n/a
nmcall = function (object, name) { var nodeArgs = array_slice(arguments, 2); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
n/a
noConflict = function () { throw new Error("Q.noConflict only works when Q is used as a global"); }
n/a
function nodeify(object, nodeback) { return Q(object).nodeify(nodeback); }
...
* pass a nodeback, they will receive the result promise.
* @param object a result (or a promise for a result)
* @param {Function} nodeback a Node.js-style callback
* @returns either the promise or nothing
*/
Q.nodeify = nodeify;
function nodeify(object, nodeback) {
return Q(object).nodeify(nodeback);
}
Promise.prototype.nodeify = function (nodeback) {
if (nodeback) {
this.then(function (value) {
Q.nextTick(function () {
nodeback(null, value);
...
npost = function (object, name, args) { return Q(object).npost(name, args); }
...
* @param {String} name name of the method of object
* @param {Array} args arguments to pass to the method; the callback
* will be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
Q.nmapply = // XXX As proposed by "Redsandro"
Q.npost = function (object, name, args) {
return Q(object).npost(name, args);
};
Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
Promise.prototype.npost = function (name, args) {
var nodeArgs = array_slice(args || []);
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
...
nsend = function (object, name) { var nodeArgs = array_slice(arguments, 2); var deferred = defer(); nodeArgs.push(deferred.makeNodeResolver()); Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject); return deferred.promise; }
n/a
passByCopy = function (object) { //freeze(object); //passByCopies.set(object, true); return object; }
n/a
post = function (object, name, args) { return Q(object).dispatch("post", [name, args]); }
...
```
direct manipulation using a promise as a proxy
-------------------------- -------------------------------
value.foo promise.get("foo")
value.foo = value promise.put("foo", value)
delete value.foo promise.del("foo")
value.foo(...args) promise.post("foo", [args])
value.foo(...args) promise.invoke("foo", ...args)
value(...args) promise.fapply([args])
value(...args) promise.fcall(...args)
```
If the promise is a proxy for a remote object, you can shave
round-trips by using these functions instead of ``then``. To take
...
function progress(object, progressed) { return Q(object).then(void 0, void 0, progressed); }
...
promise.
## 0.8.9
- Added ``nend``
- Added preliminary progress notification support, via
``promise.then(onFulfilled, onRejected, onProgress)``,
``promise.progress(onProgress)``, and ``deferred.notify(...progressData)``.
- Made ``put`` and ``del`` return the object acted upon for easier chaining.
#84
- Fixed coercion cycles with cooperating promises. #106
## 0.8.7
- Support [Montage Require](http://github.com/kriskowal/mr)
...
function promise(resolver) { if (typeof resolver !== "function") { throw new TypeError("resolver must be a function."); } var deferred = defer(); try { resolver(deferred.resolve, deferred.reject, deferred.notify); } catch (reason) { deferred.reject(reason); } return deferred.promise; }
...
and the message now includes the duration of the timeout in
miliseconds. This doesn't constitute (in my opinion) a
backward-incompatibility since it is a change of an undocumented and
unspecified public behavior, but if you happened to depend on the
exception being a string, you will need to revise your code.
- Added ``deferred.makeNodeResolver()`` to replace the more cryptic
``deferred.node()`` method.
- Added experimental ``Q.promise(maker(resolve, reject))`` to make a
promise inside a callback, such that thrown exceptions in the
callback are converted and the resolver and rejecter are arguments.
This is a shorthand for making a deferred directly and inspired by
@gozala’s stream constructor pattern and the Microsoft Windows Metro
Promise constructor interface.
- Added experimental ``Q.begin()`` that is intended to kick off chains
of ``.then`` so that each of these can be reordered without having to
...
function promised(callback) { return function () { return spread([this, all(arguments)], function (self, args) { return callback.apply(self, args); }); }; }
...
/**
* The promised function decorator ensures that any promise arguments
* are settled and passed as values (`this` is also settled and passed
* as a value). It will also ensure that the result of a function is
* always a promise.
*
* @example
* var add = Q.promised(function (a, b) {
* return a + b;
* });
* add(Q(a), Q(B));
*
* @param {function} callback The function to decorate
* @returns {function} a function that has been decorated.
*/
...
function race(answerPs) { return promise(function (resolve, reject) { // Switch to this once we can assume at least ES5 // answerPs.forEach(function (answerP) { // Q(answerP).then(resolve, reject); // }); // Use this in the meantime for (var i = 0, len = answerPs.length; i < len; i++) { Q(answerPs[i]).then(resolve, reject); } }); }
n/a
function reject(reason) { var rejection = Promise({ "when": function (rejected) { // note that the error has been handled if (rejected) { untrackRejection(this); } return rejected ? rejected(reason) : this; } }, function fallback() { return this; }, function inspect() { return { state: "rejected", reason: reason }; }); // Note that the reason has not been handled. trackRejection(rejection, reason); return rejection; }
...
* promise.
* @returns a nodeback
*/
defer.prototype.makeNodeResolver = function () {
var self = this;
return function (error, value) {
if (error) {
self.reject(error);
} else if (arguments.length > 2) {
self.resolve(array_slice(arguments, 1));
} else {
self.resolve(value);
}
};
};
...
function resetUnhandledRejections() { unhandledReasons.length = 0; unhandledRejections.length = 0; if (!trackUnhandledRejections) { trackUnhandledRejections = true; } }
n/a
function _return(value) { throw new QReturnValue(value); }
...
* var bar = yield getBarPromise();
* return foo + bar;
* })
* // Older SpiderMonkey style
* Q.async(function () {
* var foo = yield getFooPromise();
* var bar = yield getBarPromise();
* Q.return(foo + bar);
* })
*/
Q["return"] = _return;
function _return(value) {
throw new QReturnValue(value);
}
...
send = function (object, name) { return Q(object).dispatch("post", [name, array_slice(arguments, 2)]); }
...
var request = new XMLHttpRequest();
var deferred = Q.defer();
request.open("GET", url, true);
request.onload = onload;
request.onerror = onerror;
request.onprogress = onprogress;
request.send();
function onload() {
if (request.status === 200) {
deferred.resolve(request.responseText);
} else {
deferred.reject(new Error("Status code was " + request.status));
}
...
set = function (object, key, value) { return Q(object).dispatch("set", [key, value]); }
...
promise.resolve = Q; // ES6
// XXX experimental. This method is a way to denote that a local value is
// serializable and should be immediately dispatched to a remote upon request,
// instead of passing a reference.
Q.passByCopy = function (object) {
//freeze(object);
//passByCopies.set(object, true);
return object;
};
Promise.prototype.passByCopy = function () {
//freeze(object);
//passByCopies.set(object, true);
return this;
...
function spawn(makeGenerator) { Q.done(Q.async(makeGenerator)()); }
n/a
function spread(value, fulfilled, rejected) { return Q(value).spread(fulfilled, rejected); }
...
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
This is more consistent with NodeJS and (subjectively)
more explicit and intuitive.
- WARNING: ``def`` removed. Use ``master`` instead. The
term ``def`` was too confusing to new users.
- WARNING: ``spy`` removed in favor of ``fin``.
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
- WARNING: Removed the ``Q`` function module.exports alias
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
ways, making it uncallable.
- Revised ``delay`` so that it accepts both ``(value,
timeout)`` and ``(timeout)`` variations based on
arguments length.
- Added ``ref().spread(cb(...args))``, a variant of
...
stopUnhandledRejectionTracking = function () { resetUnhandledRejections(); trackUnhandledRejections = false; }
n/a
tap = function (promise, callback) { return Q(promise).tap(callback); }
...
}
}]);
return deferred.promise;
};
Q.tap = function (promise, callback) {
return Q(promise).tap(callback);
};
/**
* Works almost like "finally", but not called for rejections.
* Original resolution value is passed through callback unaffected.
* Callback may return a promise that will be awaited for.
* @param {Function} callback
...
thenReject = function (promise, reason) { return Q(promise).thenReject(reason); }
...
};
Promise.prototype.thenReject = function (reason) {
return this.then(function () { throw reason; });
};
Q.thenReject = function (promise, reason) {
return Q(promise).thenReject(reason);
};
/**
* If an object is not a promise, it is as "near" as possible.
* If a promise is rejected, it is as "near" as possible too.
* If it’s a fulfilled promise, the fulfillment value is nearer.
* If it’s a deferred promise and the deferred has been resolved, the
...
thenResolve = function (promise, value) { return Q(promise).thenResolve(value); }
...
* .tap(console.log)
* .then(...);
*/
Promise.prototype.tap = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall(value).thenResolve(value);
});
};
/**
* Registers an observer on a promise.
*
* Guarantees:
...
timeout = function (object, ms, error) { return Q(object).timeout(ms, error); }
...
* @param {Any*} promise
* @param {Number} milliseconds timeout
* @param {Any*} custom error message or Error object (optional)
* @returns a promise for the resolution of the given promise if it is
* fulfilled before the timeout, otherwise rejected.
*/
Q.timeout = function (object, ms, error) {
return Q(object).timeout(ms, error);
};
Promise.prototype.timeout = function (ms, error) {
var deferred = defer();
var timeoutId = setTimeout(function () {
if (!error || "string" === typeof error) {
error = new Error(error || "Timed out after " + ms + " ms");
...
try = function (object) { return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]); }
n/a
function when(value, fulfilled, rejected, progressed) { return Q(value).then(fulfilled, rejected, progressed); }
...
```
This is a simplified implementation of ``Q.timeout``
```javascript
function timeout(promise, ms) {
var deferred = Q.defer();
Q.when(promise, deferred.resolve);
delay(ms).then(function () {
deferred.reject(new Error("Timed out"));
});
return deferred.promise;
}
```
...