Comparing version 2.7.0 to 2.7.1
{ | ||
"name": "when", | ||
"main": "when.js", | ||
"version": "2.7.0", | ||
"version": "2.7.1", | ||
"description": "A lightweight Promises/A+ and when() implementation, plus other async goodies.", | ||
@@ -6,0 +6,0 @@ "keywords": ["Promises/A+", "promises-aplus", "promise", "promises", "deferred", "deferreds", "when", "async", "asynchronous", "cujo"], |
### 2.7.0 | ||
* Internal changes to reduce overall memory usage, along with minor performance improvements. | ||
### 2.7.0 | ||
* Added [`promise.catch`](docs/api.md#catch) and [`promise.finally`](docs/api.md#finally) as synonyms for `promise.otherwise` and `promise.ensure`. (#212) | ||
@@ -4,0 +8,0 @@ * New [browserify build](../README.md#legacy-environments-via-browserify) for those using globals. (#209) |
{ | ||
"name": "when", | ||
"version": "2.7.0", | ||
"version": "2.7.1", | ||
"description": "A lightweight Promises/A+ and when() implementation, plus other async goodies.", | ||
@@ -5,0 +5,0 @@ "keywords": ["Promises/A+", "promises-aplus", "promise", "promises", "deferred", "deferreds", "when", "async", "asynchronous", "cujo", "ender"], |
100
README.md
@@ -21,63 +21,81 @@ <a href="http://promises-aplus.github.com/promises-spec"><img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png" alt="Promises/A+ logo" align="right" /></a> | ||
Quick Start | ||
----------- | ||
Installation | ||
------------ | ||
#### AMD | ||
1. Get it | ||
- `bower install when` or `yeoman install when`, *or* | ||
- `git clone https://github.com/cujojs/when` or `git submodule add https://github.com/cujojs/when` | ||
1. Configure your loader with a package: | ||
Availble as `when` through [bower](http://bower.io) and [yeoman](https://github.com/yeoman/yo), or just clone the repo and load `when.js` from the root. When.js is AMD-compatible out of the box, so no need for shims. | ||
```js | ||
packages: [ | ||
{ name: 'when', location: 'path/to/when/', main: 'when' }, | ||
// ... other packages ... | ||
] | ||
``` | ||
#### CommonJS/Node | ||
1. `define(['when', ...], function(when, ...) { ... });` or `require(['when', ...], function(when, ...) { ... });` | ||
``` | ||
npm install when | ||
``` | ||
#### Node | ||
[More help & other environments »](docs/installation.md) | ||
1. `npm install when` | ||
1. `var when = require('when');` | ||
Usage | ||
----- | ||
#### RingoJS | ||
Promises can be used to help manage complex and/or nested callback flows in a simple manner. To get a better handle on how promise flows look and how they can be helpful, there are a couple examples below (using commonjs). | ||
1. `ringo-admin install cujojs/when` | ||
1. `var when = require('when');` | ||
This first example will print `"hello world!!!!"` if all went well, or `"drat!"` if there was a problem. It also uses [rest](https://github.com/cujojs/rest) to make an ajax request to a (fictional) external service. | ||
#### Ender | ||
```js | ||
var rest = require('rest'); | ||
1. `ender add cujojs/when` | ||
2. `var when = require('when');` | ||
fetchRemoteGreeting() | ||
.then(addExclamation) | ||
.catch(handleError) | ||
.done(function(greeting) { | ||
console.log(greeting); | ||
}); | ||
#### Legacy environments (via browserify) | ||
function fetchRemoteGreeting() { | ||
// returns a when.js promise for 'hello world' | ||
return rest('http://example.com/greeting'); | ||
} | ||
1. `git clone https://github.com/cujojs/when` | ||
1. `npm install` | ||
1. `npm run browserify` to generate `build/when.js` | ||
1. Or `npm run browserify-debug` to build with [when/monitor/console](docs/api.md#debugging-promises) enabled | ||
1. `<script src="path/to/when/build/when.js"></script>` | ||
1. `when` will be available as `window.when` | ||
1. Other modules will be available as sub-objects/functions, e.g. `window.when.fn.lift`, `window.when.sequence`. See the [full sub-namespace list in the browserify build file](build/when.browserify.js) | ||
function addExclamation(greeting) { | ||
return greeting + '!!!!' | ||
} | ||
Running the Unit Tests | ||
---------------------- | ||
function handleError(e) { | ||
return 'drat!'; | ||
} | ||
``` | ||
#### Node | ||
The second example shows off the power that comes with when's promise logic. Here, we get an array of numbers from a remote source and reduce them. The example will print `150` if all went well, and if there was a problem will print a full stack trace. | ||
Note that when.js includes the [Promises/A+ Test Suite](https://github.com/promises-aplus/promise-tests). Running unit tests in Node will run both when.js's own test suite, and the Promises/A+ Test Suite. | ||
```js | ||
var when = require('when'); | ||
var rest = require('rest'); | ||
1. `npm install` | ||
2. `npm test` | ||
when.reduce(when.map(getRemoteNumberList(), times10), sum) | ||
.done(function(result) { | ||
console.log(result); | ||
}); | ||
#### Browsers | ||
function getRemoteNumberList() { | ||
// Get a remote array [1, 2, 3, 4, 5] | ||
return rest('http://example.com/numbers').then(JSON.parse); | ||
} | ||
1. `npm install` | ||
2. `npm start` - starts buster server & prints a url | ||
3. Point browsers at <buster server url>/capture, e.g. `localhost:1111/capture` | ||
4. `npm run-script test-browser` | ||
function sum(x, y) { return x + y; } | ||
function times10(x) {return x * 10; } | ||
``` | ||
- For more examples, see [examples »](https://github.com/cujojs/when/wiki/Examples) | ||
- For the full documentation see [api docs »](docs/api.md#api) | ||
License | ||
------- | ||
Licensed under MIT. [See the license here »](LICENSE.txt) | ||
Contributing | ||
------------ | ||
Please see the [contributing guide](CONTRIBUTING.md) for more information on running tests, opening issues, and contributing code to the project. | ||
References | ||
@@ -84,0 +102,0 @@ ---------- |
@@ -10,6 +10,4 @@ /** @license MIT License (c) copyright B Cavalier & J Hann */ | ||
var when; | ||
var when = require('./when'); | ||
when = require('./when'); | ||
/** | ||
@@ -43,6 +41,3 @@ * Anamorphic unfold/map that generates values by applying | ||
}); | ||
})( | ||
typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); } | ||
// Boilerplate for AMD and Node | ||
); | ||
})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); } ); | ||
387
when.js
@@ -12,3 +12,3 @@ /** @license MIT License (c) copyright 2011-2013 original author or authors */ | ||
* @author John Hann | ||
* @version 2.7.0 | ||
* @version 2.7.1 | ||
*/ | ||
@@ -59,4 +59,10 @@ (function(define) { 'use strict'; | ||
function cast(x) { | ||
return x instanceof Promise ? x : resolve(x); | ||
/** | ||
* Creates a new promise whose fate is determined by resolver. | ||
* @param {function} resolver function(resolve, reject, notify) | ||
* @returns {Promise} promise whose fate is determine by resolver | ||
*/ | ||
function promise(resolver) { | ||
return new Promise(resolver, | ||
monitorApi.PromiseStatus && monitorApi.PromiseStatus()); | ||
} | ||
@@ -69,12 +75,86 @@ | ||
* @constructor | ||
* @param {function} sendMessage function to deliver messages to the promise's handler | ||
* @param {function?} inspect function that reports the promise's state | ||
* @returns {Promise} promise whose fate is determine by resolver | ||
* @name Promise | ||
*/ | ||
function Promise(sendMessage, inspect) { | ||
this._message = sendMessage; | ||
function Promise(resolver, status) { | ||
var self, value, consumers = []; | ||
self = this; | ||
this._status = status; | ||
this.inspect = inspect; | ||
this._when = _when; | ||
// Call the provider resolver to seal the promise's fate | ||
try { | ||
resolver(promiseResolve, promiseReject, promiseNotify); | ||
} catch(e) { | ||
promiseReject(e); | ||
} | ||
/** | ||
* Returns a snapshot of this promise's current status at the instant of call | ||
* @returns {{state:String}} | ||
*/ | ||
function inspect() { | ||
return value ? value.inspect() : toPendingState(); | ||
} | ||
/** | ||
* Private message delivery. Queues and delivers messages to | ||
* the promise's ultimate fulfillment value or rejection reason. | ||
* @private | ||
*/ | ||
function _when(resolve, notify, onFulfilled, onRejected, onProgress) { | ||
consumers ? consumers.push(deliver) : enqueue(function() { deliver(value); }); | ||
function deliver(p) { | ||
p._when(resolve, notify, onFulfilled, onRejected, onProgress); | ||
} | ||
} | ||
/** | ||
* Transition from pre-resolution state to post-resolution state, notifying | ||
* all listeners of the ultimate fulfillment or rejection | ||
* @param {*} val resolution value | ||
*/ | ||
function promiseResolve(val) { | ||
if(!consumers) { | ||
return; | ||
} | ||
var queue = consumers; | ||
consumers = undef; | ||
enqueue(function () { | ||
value = coerce(self, val); | ||
if(status) { | ||
updateStatus(value, status); | ||
} | ||
runHandlers(queue, value); | ||
}); | ||
} | ||
/** | ||
* Reject this promise with the supplied reason, which will be used verbatim. | ||
* @param {*} reason reason for the rejection | ||
*/ | ||
function promiseReject(reason) { | ||
promiseResolve(new RejectedPromise(reason)); | ||
} | ||
/** | ||
* Issue a progress event, notifying all progress listeners | ||
* @param {*} update progress event payload to pass to all listeners | ||
*/ | ||
function promiseNotify(update) { | ||
if(consumers) { | ||
var queue = consumers; | ||
enqueue(function () { | ||
runHandlers(queue, new ProgressingPromise(update)); | ||
}); | ||
} | ||
} | ||
} | ||
var promisePrototype = Promise.prototype; | ||
promisePrototype = Promise.prototype; | ||
@@ -89,10 +169,6 @@ /** | ||
promisePrototype.then = function(onFulfilled, onRejected, onProgress) { | ||
/*jshint unused:false*/ | ||
var args, sendMessage; | ||
var self = this; | ||
args = arguments; | ||
sendMessage = this._message; | ||
return _promise(function(resolve, reject, notify) { | ||
sendMessage('when', args, resolve, notify); | ||
return new Promise(function(resolve, reject, notify) { | ||
self._when(resolve, notify, onFulfilled, onRejected, onProgress); | ||
}, this._status && this._status.observed()); | ||
@@ -141,3 +217,3 @@ }; | ||
promisePrototype.done = function(handleResult, handleError) { | ||
this.then(handleResult, handleError).otherwise(crash); | ||
this.then(handleResult, handleError)['catch'](crash); | ||
}; | ||
@@ -194,2 +270,12 @@ | ||
/** | ||
* Casts x to a trusted promise. If x is already a trusted promise, it is | ||
* returned, otherwise a new trusted Promise which follows x is returned. | ||
* @param {*} x | ||
* @returns {Promise} | ||
*/ | ||
function cast(x) { | ||
return x instanceof Promise ? x : resolve(x); | ||
} | ||
/** | ||
* Returns a resolved promise. The returned promise will be | ||
@@ -200,2 +286,3 @@ * - fulfilled with promiseOrValue if it is a value, or | ||
* - rejected with promiseOrValue's reason after it is rejected | ||
* In contract to cast(x), this always creates a new Promise | ||
* @param {*} value | ||
@@ -221,3 +308,5 @@ * @return {Promise} | ||
function reject(promiseOrValue) { | ||
return when(promiseOrValue, rejected); | ||
return when(promiseOrValue, function(e) { | ||
return new RejectedPromise(e); | ||
}); | ||
} | ||
@@ -267,3 +356,3 @@ | ||
if(resolved) { | ||
return resolve(rejected(reason)); | ||
return resolve(new RejectedPromise(reason)); | ||
} | ||
@@ -283,108 +372,2 @@ resolved = true; | ||
/** | ||
* Creates a new promise whose fate is determined by resolver. | ||
* @param {function} resolver function(resolve, reject, notify) | ||
* @returns {Promise} promise whose fate is determine by resolver | ||
*/ | ||
function promise(resolver) { | ||
return _promise(resolver, monitorApi.PromiseStatus && monitorApi.PromiseStatus()); | ||
} | ||
/** | ||
* Creates a new promise, linked to parent, whose fate is determined | ||
* by resolver. | ||
* @param {function} resolver function(resolve, reject, notify) | ||
* @param {Promise?} status promise from which the new promise is begotten | ||
* @returns {Promise} promise whose fate is determine by resolver | ||
* @private | ||
*/ | ||
function _promise(resolver, status) { | ||
var self, value, consumers = []; | ||
self = new Promise(_message, inspect); | ||
self._status = status; | ||
// Call the provider resolver to seal the promise's fate | ||
try { | ||
resolver(promiseResolve, promiseReject, promiseNotify); | ||
} catch(e) { | ||
promiseReject(e); | ||
} | ||
// Return the promise | ||
return self; | ||
/** | ||
* Private message delivery. Queues and delivers messages to | ||
* the promise's ultimate fulfillment value or rejection reason. | ||
* @private | ||
* @param {String} type | ||
* @param {Array} args | ||
* @param {Function} resolve | ||
* @param {Function} notify | ||
*/ | ||
function _message(type, args, resolve, notify) { | ||
consumers ? consumers.push(deliver) : enqueue(function() { deliver(value); }); | ||
function deliver(p) { | ||
p._message(type, args, resolve, notify); | ||
} | ||
} | ||
/** | ||
* Returns a snapshot of the promise's state at the instant inspect() | ||
* is called. The returned object is not live and will not update as | ||
* the promise's state changes. | ||
* @returns {{ state:String, value?:*, reason?:* }} status snapshot | ||
* of the promise. | ||
*/ | ||
function inspect() { | ||
return value ? value.inspect() : toPendingState(); | ||
} | ||
/** | ||
* Transition from pre-resolution state to post-resolution state, notifying | ||
* all listeners of the ultimate fulfillment or rejection | ||
* @param {*|Promise} val resolution value | ||
*/ | ||
function promiseResolve(val) { | ||
if(!consumers) { | ||
return; | ||
} | ||
var queue = consumers; | ||
consumers = undef; | ||
enqueue(function () { | ||
value = coerce(self, val); | ||
if(status) { | ||
updateStatus(value, status); | ||
} | ||
runHandlers(queue, value); | ||
}); | ||
} | ||
/** | ||
* Reject this promise with the supplied reason, which will be used verbatim. | ||
* @param {*} reason reason for the rejection | ||
*/ | ||
function promiseReject(reason) { | ||
promiseResolve(rejected(reason)); | ||
} | ||
/** | ||
* Issue a progress event, notifying all progress listeners | ||
* @param {*} update progress event payload to pass to all listeners | ||
*/ | ||
function promiseNotify(update) { | ||
if(consumers) { | ||
var queue = consumers; | ||
enqueue(function () { | ||
runHandlers(queue, progressed(update)); | ||
}); | ||
} | ||
} | ||
} | ||
/** | ||
* Run a queue of functions as quickly as possible, passing | ||
@@ -400,63 +383,2 @@ * value to each. | ||
/** | ||
* Creates a fulfilled, local promise as a proxy for a value | ||
* NOTE: must never be exposed | ||
* @param {*} value fulfillment value | ||
* @returns {Promise} | ||
*/ | ||
function fulfilled(value) { | ||
return near( | ||
new NearFulfilledProxy(value), | ||
function() { return toFulfilledState(value); } | ||
); | ||
} | ||
/** | ||
* Creates a rejected, local promise with the supplied reason | ||
* NOTE: must never be exposed | ||
* @param {*} reason rejection reason | ||
* @returns {Promise} | ||
*/ | ||
function rejected(reason) { | ||
return near( | ||
new NearRejectedProxy(reason), | ||
function() { return toRejectedState(reason); } | ||
); | ||
} | ||
/** | ||
* Creates a near promise using the provided proxy | ||
* NOTE: must never be exposed | ||
* @param {object} proxy proxy for the promise's ultimate value or reason | ||
* @param {function} inspect function that returns a snapshot of the | ||
* returned near promise's state | ||
* @returns {Promise} | ||
*/ | ||
function near(proxy, inspect) { | ||
return new Promise(function (type, args, resolve) { | ||
try { | ||
resolve(proxy[type].apply(proxy, args)); | ||
} catch(e) { | ||
resolve(rejected(e)); | ||
} | ||
}, inspect); | ||
} | ||
/** | ||
* Create a progress promise with the supplied update. | ||
* @private | ||
* @param {*} update | ||
* @return {Promise} progress promise | ||
*/ | ||
function progressed(update) { | ||
return new Promise(function (type, args, _, notify) { | ||
var onProgress = args[2]; | ||
try { | ||
notify(typeof onProgress === 'function' ? onProgress(update) : update); | ||
} catch(e) { | ||
notify(e); | ||
} | ||
}); | ||
} | ||
/** | ||
* Coerces x to a trusted Promise | ||
@@ -472,3 +394,3 @@ * @param {*} x thing to coerce | ||
if (x === self) { | ||
return rejected(new TypeError()); | ||
return new RejectedPromise(new TypeError()); | ||
} | ||
@@ -485,5 +407,5 @@ | ||
? assimilate(untrustedThen, x) | ||
: fulfilled(x); | ||
: new FulfilledPromise(x); | ||
} catch(e) { | ||
return rejected(e); | ||
return new RejectedPromise(e); | ||
} | ||
@@ -504,32 +426,85 @@ } | ||
makePromisePrototype = Object.create || | ||
function(o) { | ||
function PromisePrototype() {} | ||
PromisePrototype.prototype = o; | ||
return new PromisePrototype(); | ||
}; | ||
/** | ||
* Proxy for a near, fulfilled value | ||
* @param {*} value | ||
* @constructor | ||
* Creates a fulfilled, local promise as a proxy for a value | ||
* NOTE: must never be exposed | ||
* @private | ||
* @param {*} value fulfillment value | ||
* @returns {Promise} | ||
*/ | ||
function NearFulfilledProxy(value) { | ||
function FulfilledPromise(value) { | ||
this.value = value; | ||
} | ||
NearFulfilledProxy.prototype.when = function(onResult) { | ||
return typeof onResult === 'function' ? onResult(this.value) : this.value; | ||
FulfilledPromise.prototype = makePromisePrototype(promisePrototype); | ||
FulfilledPromise.prototype.inspect = function() { | ||
return toFulfilledState(this.value); | ||
}; | ||
FulfilledPromise.prototype._when = function(resolve, _, onFulfilled) { | ||
try { | ||
resolve(typeof onFulfilled === 'function' ? onFulfilled(this.value) : this.value); | ||
} catch(e) { | ||
resolve(new RejectedPromise(e)); | ||
} | ||
}; | ||
/** | ||
* Proxy for a near rejection | ||
* @param {*} reason | ||
* @constructor | ||
* Creates a rejected, local promise as a proxy for a value | ||
* NOTE: must never be exposed | ||
* @private | ||
* @param {*} reason rejection reason | ||
* @returns {Promise} | ||
*/ | ||
function NearRejectedProxy(reason) { | ||
this.reason = reason; | ||
function RejectedPromise(reason) { | ||
this.value = reason; | ||
} | ||
NearRejectedProxy.prototype.when = function(_, onError) { | ||
if(typeof onError === 'function') { | ||
return onError(this.reason); | ||
} else { | ||
throw this.reason; | ||
RejectedPromise.prototype = makePromisePrototype(promisePrototype); | ||
RejectedPromise.prototype.inspect = function() { | ||
return toRejectedState(this.value); | ||
}; | ||
RejectedPromise.prototype._when = function(resolve, _, __, onRejected) { | ||
try { | ||
resolve(typeof onRejected === 'function' ? onRejected(this.value) : this); | ||
} catch(e) { | ||
resolve(new RejectedPromise(e)); | ||
} | ||
}; | ||
/** | ||
* Create a progress promise with the supplied update. | ||
* @private | ||
* @param {*} value progress update value | ||
* @return {Promise} progress promise | ||
*/ | ||
function ProgressingPromise(value) { | ||
this.value = value; | ||
} | ||
ProgressingPromise.prototype = makePromisePrototype(promisePrototype); | ||
ProgressingPromise.prototype._when = function(_, notify, f, r, u) { | ||
try { | ||
notify(typeof u === 'function' ? u(this.value) : this.value); | ||
} catch(e) { | ||
notify(e); | ||
} | ||
}; | ||
/** | ||
* Update a PromiseStatus monitor object with the outcome | ||
* of the supplied value promise. | ||
* @param {Promise} value | ||
* @param {PromiseStatus} status | ||
*/ | ||
function updateStatus(value, status) { | ||
@@ -711,3 +686,3 @@ value.then(statusFulfilled, statusRejected); | ||
return _promise(resolveMap); | ||
return new Promise(resolveMap); | ||
@@ -819,3 +794,3 @@ function resolveMap(resolve, reject, notify) { | ||
var reduceArray, slice, fcall, nextTick, handlerQueue, | ||
var promisePrototype, makePromisePrototype, reduceArray, slice, fcall, nextTick, handlerQueue, | ||
funcProto, call, arrayProto, monitorApi, | ||
@@ -822,0 +797,0 @@ capturedSetTimeout, cjsRequire, MutationObs, undef; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
120685
35
104
2970