Skip to content

Instantly share code, notes, and snippets.

@petsel
Created September 2, 2020 01:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petsel/4e125fb1291debf0b8d332d747cccef7 to your computer and use it in GitHub Desktop.
Save petsel/4e125fb1291debf0b8d332d747cccef7 to your computer and use it in GitHub Desktop.
implementation of a possible static `Function.afterThrowingAll` which does run a list of whatever functions failsafe
// see [https://stackoverflow.com/questions/51158888/how-to-use-common-try-catch-for-processing-every-given-function-in-javascript/63690100#63690100]
function first(...args) {
console.log("first :: does succeed :: argsList :", args);
return args.join(', ');
}
function second(...args) {
console.log("second :: going to fail :: argsList :", args);
throw new Error('2nd invocation failed.');
}
function third(...args) {
console.log("third :: going to fail :: argsList :", args);
throw new Error('3rd invocation failed.');
}
function fourth(...args) {
console.log("fourth :: does succeed :: argsList :", args);
return args.join(', ');
}
function fifth(...args) {
console.log("fifth :: does succeed :: argsList :", args);
return args.join(', ');
}
const descriptorList = [{
method: first,
argsArray: ['foo', 'bar']
}, {
method: second,
argsArray: ['baz', 'biz']
}, {
method: third,
argsArray: ['buz', 'foo']
}, {
method: fourth,
argsArray: ['bar', 'baz']
}, {
method: fourth,
argsArray: ['biz', 'buz']
}];
console.log(
'Function.afterThrowingAll(descriptorList) : ',
Function.afterThrowingAll(descriptorList)
);
// see [https://gist.github.com/petsel/9ddf5ce515f1344c84bd#file-function-afterthrowing-js]
(function (Function) {
const fctPrototype = Function.prototype;
const FUNCTION_TYPE = (typeof Function);
function isFunction(type) {
return (
(typeof type == FUNCTION_TYPE)
&& (typeof type.call == FUNCTION_TYPE)
&& (typeof type.apply == FUNCTION_TYPE)
);
}
function getSanitizedTarget(target) {
/* eslint-disable */
/* jshint ignore:start */
/* ignore jslint start */
/* no-eq-null */
return ((target != null) && target) || null;
/* ignore jslint end */
/* jshint ignore:end */
/* eslint-enable */
}
function afterThrowing/*Modifier*/(handler, target) {
target = getSanitizedTarget(target);
const proceed = this;
return (
isFunction(handler) &&
isFunction(proceed) &&
function () {
const context = target || getSanitizedTarget(this);
const args = arguments;
let result;
try {
result = proceed.apply(context, args);
} catch (exception) {
result = handler.call(context, exception, args);
}
return result;
}
) || proceed;
}
// afterThrowing.toString = () => 'afterThrowing() { [native code] }';
Object.defineProperty(fctPrototype, 'afterThrowing', {
configurable: true,
writable: true,
value: afterThrowing/*Modifier*/
});
// provide static implementation as well.
function staticAfterThrowing/*Modifier*/(proceed, handler, target) {
return afterThrowing.call(proceed, handler, target);
}
// staticAfterThrowing.toString = () => 'afterThrowing() { [native code] }';
// staticAfterThrowing.toString = () => 'staticAfterThrowing() { [native code] }';
Object.defineProperty(Function, 'afterThrowing', {
configurable: true,
writable: true,
value: staticAfterThrowing/*Modifier*/
});
}(Function));
// see [https://gist.github.com/petsel/9ddf5ce515f1344c84bd#file-function-afterthrowing-js]
//
// const staticAfterThrowing/*Modifier*/ = Function.afterThrowing;
(function (Function, Array, Object) {
const isArray = Array.isArray;
const arrayFrom = Array.from;
function getSanitizedArgsArray(argsArray) {
/* eslint-disable */
/* jshint ignore:start */
/* ignore jslint start */
/* no-eq-null */
return ((argsArray != null) && Array.from(argsArray)) || [];
/* ignore jslint end */
/* jshint ignore:end */
/* eslint-enable */
}
const FUNCTION_TYPE = (typeof Function);
function isFunction(type) {
return (
(typeof type == FUNCTION_TYPE)
&& (typeof type.call == FUNCTION_TYPE)
&& (typeof type.apply == FUNCTION_TYPE)
);
}
function isException(value) {
return (
value
&& value.hasOwnProperty('exception')
&& value.hasOwnProperty('argsArray')
&& isArray(value.argsArray)
);
}
function unifyResult(value) {
return (
(isException(value) && value)
|| { value }
);
}
/**
* - can access the try-catch exception and the arguments
* that have been passed prior to the invocation failure.
*/
function exceptionHandler(exception, argsArray) {
return {
exception,
argsArray: arrayFrom(argsArray)
}
}
/**
* map functionality which returns the result of invoking a method via its descriptor.
*
* - an `afterThrowing` modified function does always return either the result of the
* original function's/method's invocation or the return value of its 'afterThrowing'
* exception handler.
*/
function getInvocationResult(descriptor) {
return unifyResult(descriptor.method // - modify original function/method towards an
.afterThrowing(exceptionHandler) // `afterThrowing` handling of its try-catch result.
.apply(
descriptor.target,
getSanitizedArgsArray(descriptor.argsArray)
)
);
}
function afterThrowingAll(descriptorList) {
let result;
if (
isArray(descriptorList)
&& descriptorList.every(descriptor => isFunction(descriptor.method))
) {
result = descriptorList.map(getInvocationResult);
}
return result;
}
Object.defineProperty(Function, 'afterThrowingAll', {
configurable: true,
writable: true,
value: afterThrowingAll
});
}(Function, Array, Object));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment