You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.5 KiB
146 lines
4.5 KiB
"use strict"; |
|
module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) { |
|
var util = require("./util"); |
|
var CancellationError = Promise.CancellationError; |
|
var errorObj = util.errorObj; |
|
var catchFilter = require("./catch_filter")(NEXT_FILTER); |
|
|
|
function PassThroughHandlerContext(promise, type, handler) { |
|
this.promise = promise; |
|
this.type = type; |
|
this.handler = handler; |
|
this.called = false; |
|
this.cancelPromise = null; |
|
} |
|
|
|
PassThroughHandlerContext.prototype.isFinallyHandler = function() { |
|
return this.type === 0; |
|
}; |
|
|
|
function FinallyHandlerCancelReaction(finallyHandler) { |
|
this.finallyHandler = finallyHandler; |
|
} |
|
|
|
FinallyHandlerCancelReaction.prototype._resultCancelled = function() { |
|
checkCancel(this.finallyHandler); |
|
}; |
|
|
|
function checkCancel(ctx, reason) { |
|
if (ctx.cancelPromise != null) { |
|
if (arguments.length > 1) { |
|
ctx.cancelPromise._reject(reason); |
|
} else { |
|
ctx.cancelPromise._cancel(); |
|
} |
|
ctx.cancelPromise = null; |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
function succeed() { |
|
return finallyHandler.call(this, this.promise._target()._settledValue()); |
|
} |
|
function fail(reason) { |
|
if (checkCancel(this, reason)) return; |
|
errorObj.e = reason; |
|
return errorObj; |
|
} |
|
function finallyHandler(reasonOrValue) { |
|
var promise = this.promise; |
|
var handler = this.handler; |
|
|
|
if (!this.called) { |
|
this.called = true; |
|
var ret = this.isFinallyHandler() |
|
? handler.call(promise._boundValue()) |
|
: handler.call(promise._boundValue(), reasonOrValue); |
|
if (ret === NEXT_FILTER) { |
|
return ret; |
|
} else if (ret !== undefined) { |
|
promise._setReturnedNonUndefined(); |
|
var maybePromise = tryConvertToPromise(ret, promise); |
|
if (maybePromise instanceof Promise) { |
|
if (this.cancelPromise != null) { |
|
if (maybePromise._isCancelled()) { |
|
var reason = |
|
new CancellationError("late cancellation observer"); |
|
promise._attachExtraTrace(reason); |
|
errorObj.e = reason; |
|
return errorObj; |
|
} else if (maybePromise.isPending()) { |
|
maybePromise._attachCancellationCallback( |
|
new FinallyHandlerCancelReaction(this)); |
|
} |
|
} |
|
return maybePromise._then( |
|
succeed, fail, undefined, this, undefined); |
|
} |
|
} |
|
} |
|
|
|
if (promise.isRejected()) { |
|
checkCancel(this); |
|
errorObj.e = reasonOrValue; |
|
return errorObj; |
|
} else { |
|
checkCancel(this); |
|
return reasonOrValue; |
|
} |
|
} |
|
|
|
Promise.prototype._passThrough = function(handler, type, success, fail) { |
|
if (typeof handler !== "function") return this.then(); |
|
return this._then(success, |
|
fail, |
|
undefined, |
|
new PassThroughHandlerContext(this, type, handler), |
|
undefined); |
|
}; |
|
|
|
Promise.prototype.lastly = |
|
Promise.prototype["finally"] = function (handler) { |
|
return this._passThrough(handler, |
|
0, |
|
finallyHandler, |
|
finallyHandler); |
|
}; |
|
|
|
|
|
Promise.prototype.tap = function (handler) { |
|
return this._passThrough(handler, 1, finallyHandler); |
|
}; |
|
|
|
Promise.prototype.tapCatch = function (handlerOrPredicate) { |
|
var len = arguments.length; |
|
if(len === 1) { |
|
return this._passThrough(handlerOrPredicate, |
|
1, |
|
undefined, |
|
finallyHandler); |
|
} else { |
|
var catchInstances = new Array(len - 1), |
|
j = 0, i; |
|
for (i = 0; i < len - 1; ++i) { |
|
var item = arguments[i]; |
|
if (util.isObject(item)) { |
|
catchInstances[j++] = item; |
|
} else { |
|
return Promise.reject(new TypeError( |
|
"tapCatch statement predicate: " |
|
+ "expecting an object but got " + util.classString(item) |
|
)); |
|
} |
|
} |
|
catchInstances.length = j; |
|
var handler = arguments[i]; |
|
return this._passThrough(catchFilter(catchInstances, handler, this), |
|
1, |
|
undefined, |
|
finallyHandler); |
|
} |
|
|
|
}; |
|
|
|
return PassThroughHandlerContext; |
|
};
|
|
|