Created
September 2, 2020 01:57
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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) | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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