| /** @license MIT License (c) copyright 2010-2014 original author or authors */ |
| /** @author Brian Cavalier */ |
| /** @author John Hann */ |
| |
| (function(define) { 'use strict'; |
| define(function() { |
| |
| return function flow(Promise) { |
| |
| var resolve = Promise.resolve; |
| var reject = Promise.reject; |
| var origCatch = Promise.prototype['catch']; |
| |
| /** |
| * Handle the ultimate fulfillment value or rejection reason, and assume |
| * responsibility for all errors. If an error propagates out of result |
| * or handleFatalError, it will be rethrown to the host, resulting in a |
| * loud stack track on most platforms and a crash on some. |
| * @param {function?} onResult |
| * @param {function?} onError |
| * @returns {undefined} |
| */ |
| Promise.prototype.done = function(onResult, onError) { |
| this._handler.visit(this._handler.receiver, onResult, onError); |
| }; |
| |
| /** |
| * Add Error-type and predicate matching to catch. Examples: |
| * promise.catch(TypeError, handleTypeError) |
| * .catch(predicate, handleMatchedErrors) |
| * .catch(handleRemainingErrors) |
| * @param onRejected |
| * @returns {*} |
| */ |
| Promise.prototype['catch'] = Promise.prototype.otherwise = function(onRejected) { |
| if (arguments.length < 2) { |
| return origCatch.call(this, onRejected); |
| } |
| |
| if(typeof onRejected !== 'function') { |
| return this.ensure(rejectInvalidPredicate); |
| } |
| |
| return origCatch.call(this, createCatchFilter(arguments[1], onRejected)); |
| }; |
| |
| /** |
| * Wraps the provided catch handler, so that it will only be called |
| * if the predicate evaluates truthy |
| * @param {?function} handler |
| * @param {function} predicate |
| * @returns {function} conditional catch handler |
| */ |
| function createCatchFilter(handler, predicate) { |
| return function(e) { |
| return evaluatePredicate(e, predicate) |
| ? handler.call(this, e) |
| : reject(e); |
| }; |
| } |
| |
| /** |
| * Ensures that onFulfilledOrRejected will be called regardless of whether |
| * this promise is fulfilled or rejected. onFulfilledOrRejected WILL NOT |
| * receive the promises' value or reason. Any returned value will be disregarded. |
| * onFulfilledOrRejected may throw or return a rejected promise to signal |
| * an additional error. |
| * @param {function} handler handler to be called regardless of |
| * fulfillment or rejection |
| * @returns {Promise} |
| */ |
| Promise.prototype['finally'] = Promise.prototype.ensure = function(handler) { |
| if(typeof handler !== 'function') { |
| return this; |
| } |
| |
| return this.then(function(x) { |
| return runSideEffect(handler, this, identity, x); |
| }, function(e) { |
| return runSideEffect(handler, this, reject, e); |
| }); |
| }; |
| |
| function runSideEffect (handler, thisArg, propagate, value) { |
| var result = handler.call(thisArg); |
| return maybeThenable(result) |
| ? propagateValue(result, propagate, value) |
| : propagate(value); |
| } |
| |
| function propagateValue (result, propagate, x) { |
| return resolve(result).then(function () { |
| return propagate(x); |
| }); |
| } |
| |
| /** |
| * Recover from a failure by returning a defaultValue. If defaultValue |
| * is a promise, it's fulfillment value will be used. If defaultValue is |
| * a promise that rejects, the returned promise will reject with the |
| * same reason. |
| * @param {*} defaultValue |
| * @returns {Promise} new promise |
| */ |
| Promise.prototype['else'] = Promise.prototype.orElse = function(defaultValue) { |
| return this.then(void 0, function() { |
| return defaultValue; |
| }); |
| }; |
| |
| /** |
| * Shortcut for .then(function() { return value; }) |
| * @param {*} value |
| * @return {Promise} a promise that: |
| * - is fulfilled if value is not a promise, or |
| * - if value is a promise, will fulfill with its value, or reject |
| * with its reason. |
| */ |
| Promise.prototype['yield'] = function(value) { |
| return this.then(function() { |
| return value; |
| }); |
| }; |
| |
| /** |
| * Runs a side effect when this promise fulfills, without changing the |
| * fulfillment value. |
| * @param {function} onFulfilledSideEffect |
| * @returns {Promise} |
| */ |
| Promise.prototype.tap = function(onFulfilledSideEffect) { |
| return this.then(onFulfilledSideEffect)['yield'](this); |
| }; |
| |
| return Promise; |
| }; |
| |
| function rejectInvalidPredicate() { |
| throw new TypeError('catch predicate must be a function'); |
| } |
| |
| function evaluatePredicate(e, predicate) { |
| return isError(predicate) ? e instanceof predicate : predicate(e); |
| } |
| |
| function isError(predicate) { |
| return predicate === Error |
| || (predicate != null && predicate.prototype instanceof Error); |
| } |
| |
| function maybeThenable(x) { |
| return (typeof x === 'object' || typeof x === 'function') && x !== null; |
| } |
| |
| function identity(x) { |
| return x; |
| } |
| |
| }); |
| }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); })); |