twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

finally.js (4613B)


      1 "use strict";
      2 module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) {
      3 var util = require("./util");
      4 var CancellationError = Promise.CancellationError;
      5 var errorObj = util.errorObj;
      6 var catchFilter = require("./catch_filter")(NEXT_FILTER);
      7 
      8 function PassThroughHandlerContext(promise, type, handler) {
      9     this.promise = promise;
     10     this.type = type;
     11     this.handler = handler;
     12     this.called = false;
     13     this.cancelPromise = null;
     14 }
     15 
     16 PassThroughHandlerContext.prototype.isFinallyHandler = function() {
     17     return this.type === 0;
     18 };
     19 
     20 function FinallyHandlerCancelReaction(finallyHandler) {
     21     this.finallyHandler = finallyHandler;
     22 }
     23 
     24 FinallyHandlerCancelReaction.prototype._resultCancelled = function() {
     25     checkCancel(this.finallyHandler);
     26 };
     27 
     28 function checkCancel(ctx, reason) {
     29     if (ctx.cancelPromise != null) {
     30         if (arguments.length > 1) {
     31             ctx.cancelPromise._reject(reason);
     32         } else {
     33             ctx.cancelPromise._cancel();
     34         }
     35         ctx.cancelPromise = null;
     36         return true;
     37     }
     38     return false;
     39 }
     40 
     41 function succeed() {
     42     return finallyHandler.call(this, this.promise._target()._settledValue());
     43 }
     44 function fail(reason) {
     45     if (checkCancel(this, reason)) return;
     46     errorObj.e = reason;
     47     return errorObj;
     48 }
     49 function finallyHandler(reasonOrValue) {
     50     var promise = this.promise;
     51     var handler = this.handler;
     52 
     53     if (!this.called) {
     54         this.called = true;
     55         var ret = this.isFinallyHandler()
     56             ? handler.call(promise._boundValue())
     57             : handler.call(promise._boundValue(), reasonOrValue);
     58         if (ret === NEXT_FILTER) {
     59             return ret;
     60         } else if (ret !== undefined) {
     61             promise._setReturnedNonUndefined();
     62             var maybePromise = tryConvertToPromise(ret, promise);
     63             if (maybePromise instanceof Promise) {
     64                 if (this.cancelPromise != null) {
     65                     if (maybePromise._isCancelled()) {
     66                         var reason =
     67                             new CancellationError("late cancellation observer");
     68                         promise._attachExtraTrace(reason);
     69                         errorObj.e = reason;
     70                         return errorObj;
     71                     } else if (maybePromise.isPending()) {
     72                         maybePromise._attachCancellationCallback(
     73                             new FinallyHandlerCancelReaction(this));
     74                     }
     75                 }
     76                 return maybePromise._then(
     77                     succeed, fail, undefined, this, undefined);
     78             }
     79         }
     80     }
     81 
     82     if (promise.isRejected()) {
     83         checkCancel(this);
     84         errorObj.e = reasonOrValue;
     85         return errorObj;
     86     } else {
     87         checkCancel(this);
     88         return reasonOrValue;
     89     }
     90 }
     91 
     92 Promise.prototype._passThrough = function(handler, type, success, fail) {
     93     if (typeof handler !== "function") return this.then();
     94     return this._then(success,
     95                       fail,
     96                       undefined,
     97                       new PassThroughHandlerContext(this, type, handler),
     98                       undefined);
     99 };
    100 
    101 Promise.prototype.lastly =
    102 Promise.prototype["finally"] = function (handler) {
    103     return this._passThrough(handler,
    104                              0,
    105                              finallyHandler,
    106                              finallyHandler);
    107 };
    108 
    109 
    110 Promise.prototype.tap = function (handler) {
    111     return this._passThrough(handler, 1, finallyHandler);
    112 };
    113 
    114 Promise.prototype.tapCatch = function (handlerOrPredicate) {
    115     var len = arguments.length;
    116     if(len === 1) {
    117         return this._passThrough(handlerOrPredicate,
    118                                  1,
    119                                  undefined,
    120                                  finallyHandler);
    121     } else {
    122          var catchInstances = new Array(len - 1),
    123             j = 0, i;
    124         for (i = 0; i < len - 1; ++i) {
    125             var item = arguments[i];
    126             if (util.isObject(item)) {
    127                 catchInstances[j++] = item;
    128             } else {
    129                 return Promise.reject(new TypeError(
    130                     "tapCatch statement predicate: "
    131                     + "expecting an object but got " + util.classString(item)
    132                 ));
    133             }
    134         }
    135         catchInstances.length = j;
    136         var handler = arguments[i];
    137         return this._passThrough(catchFilter(catchInstances, handler, this),
    138                                  1,
    139                                  undefined,
    140                                  finallyHandler);
    141     }
    142 
    143 };
    144 
    145 return PassThroughHandlerContext;
    146 };