It is possible catch several exceptions with only one try-catch block? - javascript

In this javascript code f.init() control the entire flow of the program:
var f = function() {
return {
init: function(var1) {
try {
f.f1(1)
} catch (e) {
alert(e);
}
try {
f.f2(1)
} catch (e) {
alert(e);
}
// ...
// more try-catch blocks
// ...
},
f1: function() {
throw Error('f1 called');
},
f2: function() {
throw Error('f2 called');
}
};
}();
f.init();
How I could centralize all exceptions management in only one try-catch block? Something like this:
var f = function() {
return {
init: function(var1) {
f.f1(1) // this cut the control flow if thrown some error
f.f2(1) // so this is not called
},
f1: function() {
throw Error('f1 called');
},
f2: function() {
throw Error('f2 called');
}
};
}();
try {
f.init();
} catch (e) {
alert(e);
}
The previous code cut the flow after thrown some error.

You can't. Once an error is thrown, the program flow breaks.

You cannot . But there is a trick to handle multiple-catch :
try{
try{
firstTrial();
}
catch(e1){
secondTrial();
}
}catch(e2){
thirdTrial();
}

Related

forkJoin never finishes even though complete() is called

I am trying to run a forkJoin, but it isn't running the pipe(). It runs the two methods in the array, but not the result, and I am not sure why...
in the onStart() is where I am calling forkJoin() but here never prints to the console. Am I missing a sub.complete() somewhere?
export MyClass extends ParentClass {
override onStart() {
super.onStart();
forkJoin([this.#addPhysics3D(), this.#addPhysics2D()]).pipe(
tap(() => {
console.log('here');
})
).subscribe();
}
#addPhysics3D() {
return new Observable<void>(sub => {
try {
import('#engine/physics').then(physics => {
if (!physics) return sub.complete();
if (Reflect.hasMetadata(physics.PHYSICS_RIGIDBODY, this.target)) {
const world = Injector.get(physics.World);
world?.add(this);
}
return sub.complete();
});
} catch (e) { sub.complete(); }
});
}
#addPhysics2D() {
return new Observable<void>(sub => {
try {
import('#engine/physics2d').then(physics => {
if (!physics) return sub.complete();
if (Reflect.hasMetadata(physics.PHYSICS2D_RIGIDBODY, this.target)) {
const world = Injector.get(physics.World2D);
world?.add(this);
}
return sub.complete();
});
} catch (e) { sub.complete(); }
});
}
}
Problem
Seems like, you never catch errors caused by import
Clearly #engine/physics2d doesn't exists in the current environment, but no console log appear:
try {
import ('#engine/physics2d').then(console.log)
} catch (error) {
console.log('error', error)
}
Solution
Use await to make promise throw an error
(async() => {
try {
await
import ('#engine/physics2d')
} catch (error) {
console.log('error', error)
}
})()
Use .catch on the promise
import ('#engine/physics2d').then(console.log).catch(error => console.log('error', error))
The last one will probably work better with your codebase

Error handling inside addEventListener callback

How do developers structure their programs if they want to have a top-level error handling function?
The immediate thought that came into my mind was to wrap a try..catch to the main function, however, this does not trigger errors from callbacks?
try {
main();
} catch(error) {
alert(error)
}
function main() {
// This works
throw new Error('Error from main()');
document.querySelector('button').addEventListener('click', function() {
// This doesn throw
throw new Error ('Error from click callback');
})
}
<button>
Click me to see my callback error
</button>
Try-catch functionality around already existing functions/methods gets achieved best by wrapper approaches.
For the OP's use case one needs a modifying wrapper function which explicitly targets the handling of "after throwing" ...
// - try-catch wrapper which specifically
// targets the handling of "after throwing".
function afterThrowingModifier(proceed, handler, target) {
return function (...argsArray) {
let result;
try {
result = proceed.apply(target, argsArray);
} catch (exception) {
result = handler.call(target, exception, argsArray);
}
return result;
}
}
function failingClickHandler(/* event */) {
throw new Error('Error from click callback');
}
function afterTrowingHandler(error, [ event ]) {
const { message, stack } = error
const { type, currentTarget } = event;
console.log({
error: { message, stack },
event: { type, currentTarget },
});
}
function main() {
document
.querySelector('button')
.addEventListener('click', afterThrowingModifier(
failingClickHandler, afterTrowingHandler
));
}
main();
body { margin: 0; }
.as-console-wrapper { min-height: 85%!important; }
<button>
Click me to see my callback error
</button>
One of cause can implement prototype based abstractions for a function modifying failure handling like afterThrowing or afterFinally. Then the above main example code changes to something more expressive like ...
function afterTrowingHandler(error, [ event ]) {
const { message, stack } = error
const { type, currentTarget } = event;
console.log({
error: { message, stack },
event: { type, currentTarget },
});
}
function main() {
document
.querySelector('button')
.addEventListener('click', (function (/* event */) {
throw new Error('Error from click callback');
}).afterThrowing(afterTrowingHandler));
}
main();
body { margin: 0; }
.as-console-wrapper { min-height: 85%!important; }
<button>
Click me to see my callback error
</button>
<script>
(function (Function) {
function isFunction(value) {
return (
typeof value === 'function' &&
typeof value.call === 'function' &&
typeof value.apply === 'function'
);
}
function getSanitizedTarget(value) {
return value ?? null;
}
function afterThrowing/*Modifier*/(handler, target) {
target = getSanitizedTarget(target);
const proceed = this;
return (
isFunction(handler) &&
isFunction(proceed) &&
function afterThrowingType(...argumentArray) {
const context = getSanitizedTarget(this) ?? target;
let result;
try {
// try the invocation of the original function.
result = proceed.apply(context, argumentArray);
} catch (exception) {
result = handler.call(context, exception, argumentArray);
}
return result;
}
) || proceed;
}
// afterThrowing.toString = () => 'afterThrowing() { [native code] }';
Object.defineProperty(Function.prototype, 'afterThrowing', {
configurable: true,
writable: true,
value: afterThrowing/*Modifier*/
});
}(Function));
</script>
In javascript you can override global onerror, catching most of the errors:
window.onerror = function(message, source, lineno, colno, error) { ... };
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
In your case:
window.onerror = function(message, source, lineno, colno, error) {
console.error(message);
alert(message);
return false
};
function main() {
// This works
throw new Error('Error from main()');
document.querySelector('button').addEventListener('click', function() {
// This doesn throw
throw new Error ('Error from click callback');
})
}
main();
Some extra info:
https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror
Added after questions if Promise would raise the error, lets test:
window.onerror = (message, source, lineno,colno,error)=>{
console.error(`It does!, ${message}`);
};
const aFn = ()=>{
return new Promise((resolve)=>{
setTimeout(()=>{
throw new Error("whoops")
}, 3000);
});
}
aFn();
Result:
VM1163:2 It does!, Script error.
window.onerror # VM1163:2
error (asynchroon)
(anoniem) # VM1163:1
VM1163:7 Uncaught Error: whoops
at <anonymous>:7:19

JS Using onSuccess() syntax

I have some code and I just see to be doing something wrong with the syntax.
Here is the code:
async mymethod(onSuccess, onFailure) {
try {
// Do some here
onSuccess()
}
catch (e) {
//this was an error
}
}
What I want to do is its onSuccess() I want to do something.
Tried:
onSuccess((function() {
// Do something
}))
But there seems to be a syntax error.
How do I use onSuccess() and do something with it?
You're missing the function keyword:
async function mymethod(onSuccess, onFailure) {
try {
// Do some here
onSuccess()
}
catch (e) {
//this was an error
onFailure()
}
}
mymethod(() => alert('success'), () => alert('failure'));
Since you are using a typescript and a class you need to include the public access modifier as methods are private by default.
class Foo {
public async mymethod(onSuccess, onFailure) {
try {
// Do some here
onSuccess()
}
catch (e) {
//this was an error
onFailure()
}
}
}
const foo = new Foo();
foo.mymethod(() => { console.log('success') }, () => { console.log('failure') });

Javascript ES5/ES6 classes and error handling

Say I have a class like this
class SomeUIComponentDataStore {
async function getUser() {
try { //do something that can fail}
catch(e) {
// gracefully fail, setting portion of ui to fail state
Sentry.captureException(e); // report to some metrics service
}
}
}
I repeat that pattern for every async function. Where on failure I respond to the error, and then report it to some service (in this case that service is Sentry).
Is there anyway I can create a BaseClass, that will automatically decorate my catch statement with Sentry.caputreException(). Or do i have to manually write it each time a I see an error.
You could define a decorator to reuse that logic and decorate methods that can throw:
function catchError(target, name, descriptor) {
const original = descriptor.value;
if (typeof original === 'function') {
descriptor.value = function(...args) {
try {
return original.apply(this, args);
} catch (e) {
Sentry.captureException(e); // report to some metrics service
}
}
}
}
function catchErrorAsync(target, name, descriptor) {
const original = descriptor.value;
if (typeof original === 'function') {
descriptor.value = async function(...args) {
try {
return await original.apply(this, args);
} catch (e) {
Sentry.captureException(e); // report to some metrics service
}
}
}
}
class SomeUIComponentDataStore {
#catchErrorAsync
async getUser() {
//do something that can fail
}
#catchError
otherMethod() {
//do something that can fail
}
}
You could create a base class with the Sentry.captureException(e);, and then have overrideable functions for the custom try/catch functionality.
class BaseClass {
function onGetUser() {
throw new Error("Method not implemented");
}
function onGetUserFail() {
throw new Error("Method not implemented");
}
async function getUser() {
try {
onGetUser();
} catch (e) {
onGetUserFail();
Sentry.captureException(e);
}
}
}
class SomeUIComponentDataStore extends BaseClass {
function onGetUser() {
// do something
}
function onGetUserFail() {
// do something
}
}

How to loop async code with a try-catch block inside using generators?

This simple code would enter the catch just once.
How can I loop this with the try catch?
run(function* (gen) {
while (true) {
try {
yield request('http://www.unexistanturl.com', gen());
} catch (err) {
debug(err);
}
}
})
run(function* (gen) {
while (true) {
yield function(){
try {
request('http://www.unexistanturl.com', gen());
} catch (err) {
debug(err);
}
}();
}
})

Categories

Resources