continue execution after a throw in JS - javascript

i have this function in my code and I'm using throw to create meaningful errors (rather than failing silently). However, when i structure my function this way, if i call defineSandbox() with an error, it stops the whole script.
//defineSandbox is in an object, for now i name "myObj"
var defineSandbox = function (sandboxName,SandboxDefinition) {
//validation
if(!is.validString(sandboxName)) {
throw statusMessages.sandbox.invalidName;
}
if(!is.validFunction (SandboxDefinition)) {
throw statusMessages.sandbox.invalidDefinition;
}
//...some more validation here
//...sandbox builder code if validation passes (code wasn't returned)
registered.sandboxes[sandboxName] = newSandbox;
};
//intentional error, non-string name
myObj.defineSandbox(false);
//...and so the rest of the script from here down is not executed
//i can't build this sandbox anymore
myObj.defineSandbox('mySandbox',function(){...});
what i would like to have is if one call fails, it gives out an error but still tries to continue to run the script. how do i structure this code so that i can achieve that?

Typically, you don't want to continue execution when you manually throw a new error. If you want to have it for a logging purpose, you should consider an self-created internal solution.
However, to catch a thrown error you need to invoke a try / catch statement.
try {
myObj.defineSandbox(false);
} catch( ex ) {
// execution continues here when an error was thrown. You can also inspect the `ex`ception object
}
By the way, you can also specify which kind of error you want to throw, for instance a type error or a reference error like
throw new TypeError();
throw new ReferenceError();
throw new SyntaxError();
etc.
Complete list: MDN

console.error() will not throw an error, but will display an error in your log without halting execution.

If you would like to report the caught error so that window.onerror will fire, you can dispatch an error event in your catch block:
try {
}
catch (error)
{
const e = new ErrorEvent('error', {message:'my error', error:error})
window.dispatchEvent(e)
}
I found this useful for catching and reporting errors in a for loop while still continuing with the loop.

If you are trying to aggregate all the errors instead of just throwing one of them, then you should create an array of the issues (exceptions) and then throw the array, instead of just the first issue you hit.

You need to catch thrown errors if you want to deal with them nicely. In your example:
//intentional error, non-string name
try {
myObj.defineSandbox(false);
} catch(error) {
alert("Error defining sandbox: " + error);
}
And then subsequent code will still continue to run.

var bear = {};
(function () {
bear.errorProcesser = function ( e ) {
console.log( e );
}
bear.define = function ( name, fn ) {
try {
if( typeof name != "string" || typeof fn != "function"){
throw new Error ("some error");
}
bear[name] = fn;
} catch (e){
bear.errorProcesser ( e );
}
}
})()
bear.define ( "testfunc", {} );

Is it just try-catch you're searching for?

Related

How to make protractor test fail if function fails?

So basically I have some helpers method to help me debug my protractor test cases, one of my main ones is tho wait for an element to be clickable, I'm creating this loop to give the necessary time for protractor to find and make sure the element is enabled, but when an element is not found, either by the element not being found or a typo on my scrip, I would like the test run to STOP and mark it as a FAILURE..
async WaitToBeClickable(element){
try{
for(var i = 0; i <= 3000; i++){
var wait = await browser.wait(this.EC.elementToBeClickable(element), i);
if(wait == true){
break;
}else{
//this is where I want to fail
}
}
}catch(err){
//this is where I want to fail
await console.log(`WAIT TO BE CLICKABLE FAILED:\n${element.parentElementArrayFinder.locator_.value}\n\nError:\n${err}\n`);
}
};
this would help me a LOT debugging my script since I'm working on VSC, but I can not seem to find a way yet to make the test FAIL and thereby to CLOSE the browser at the first fail, I've seen protractor-fail-fast and protractor-bail-fast but it seems to be for the jasmine test cases not for function, I WOULD REALLY APPRECIATE any help please, protractor its driving me a bit nuts lol...
//method
const checkData = () = {
return new Promise((resolve)=>{
if(true){
// Success case
return resolve(true)
}
else{
// Fail case
return reject(false)
}
})
}
//Specfile
it('sample test',async ()=>{
Let data = await checkData();
expect(data).toEqual(true);
})
Based on resolved value test will pass or fail
If you function throws error you can just use the done function that jasmine provides
Example:
it('should do something', async done => {
try {
await weDoSomething();
} catch (e) {
done.fail(e); // mark test as failed
}
done(); // mark test as done
}, 1 * 60 * 1000);
async function weDoSomething() {
throw Error('failed function');
}
Did you try simply re-throwing the error in the catch? I believe that should cause the test to fail.
Comments:
You do not need to await a console.log as it is an synchronous operation.
broser.waits throw exceptions when the element is not found within the timeout period, it appears your for loop is not required at all.
This function will wait 3000ms for the element to be clickable and if that does not happen it will throw an exception which will be caught in the catch. It will log the message and then rethrow the error which will fail your test (assuming the error is not being caught and handled further up)
async WaitToBeClickable(element){
try {
await browser.wait(this.EC.elementToBeClickable(element), 3000);
} catch (err) {
console.log(`WAIT TO BE CLICKABLE FAILED:\n${element.parentElementArrayFinder.locator_.value}\n\nError:\n${err}\n`);
throw new Error(err);
}
};

Incorrect error handling when using nested try / catch blocks

I have error handling set up using try/catch blocks, which in its simplified form looks like this
try {
// .. Some application logic
try {
// .. some async api code
} catch (e) {
throw new Error("Api Error")
}
return true;
} catch (e) {
throw new Error("Unknown Error")
}
And the issue is, whenever I expect "Api Error" to be returned I get "Unknown Error" it seems like all errors are propagated to the outermost catch?
Is there a way to avoid this or another approach that allows for nested error handling?
In your code, check if exception is happening inside the first try block. If so, the inner try won't be executed.
try {
// .. Some application logic
// exception occurs here
// below code is not executed and the control is given to catch block
try {
//this did not execute
// .. some async api code
} catch (e) {
throw new Error("Api Error")
}
return true;
}
catch (e) {
//control came here
throw new Error("Unknown Error")
}
This is also a possible case:
try {
// .. Some application logic
// no exceptions occur here
// below code is executed
try {
//this did not execute
//exception here
// .. some async api code
} catch (e) {
//control came here and this threw APIerror
throw new Error("Api Error")
}
//this did not execute as the previous catch block raised another exception
return true;
}
catch (e) {
//control came here
throw new Error("Unknown Error")
}
Hope this helps :)

How to differentiate between operational and programmer errors in promise chains?

So I want to know how to make sure that my Node application will crash if it comes upon a programmer error(undefined variable, reference error, syntax error...). However, if I am using promise chains then the final catch() will catch all possible errors including programmer errors.
For example:
PromiseA()
.then((result) => {
foo.bar(); //UNDEFINED FUNCTION HERE!!!!!
return PromiseB(result);
})
.catch(
//handle errors here
)
Now the catch() statement will also catch the really bad error of an undefined function and then try to handle it. I need a way for my program to crash when it comes up against errors like these.
EDIT: I also just realized that even if I throw an error in the last catch it will just be consumed by the promise chain :-[. How am I supposed to deal with that?
Basically, what you want to do is to handle those errors that you can potentially recover from. These errors are usually something you throw in your code. For example, if an item is not found in a DB some libraries will throw an Error. They'll add a type property or some other property to differentiate the different type of errors.
You can also potentially subclass the Error class and use instanceof to differentiate each error.
class myOwnError extends Error {}
Then:
Prom.catch(err => {
if(err instanceof myOwnError){ /* handle error here */ }
else { throw err; }
});
If you want to avoid if/chains, you can use a switch on error.constructor:
switch(err.constructor){
case myOwnError:
break;
case someOtherError:
break;
default:
throw err;
}
You can also use an a Map or regular objects by creating functions for each possible error and storing them. With a Map:
let m = new Map();
m.set(myOWnError, function(e){ /*handle error here*/ });
m.set(myOtherError, function(e){ /*handle other error here*/ });
Then just do:
Prom.catch(err => {
let fn = m.get(err.constructor);
if(fn){ return fn(err); }
else { throw err; }
});
Disclaimer: Below is a description what we do at the company I work. The package linked is written by us.
What we do is to catch all errors and sort them into programmer and operational errors.
We've made small library to help us: https://www.npmjs.com/package/oops-error
For promise chains we use:
import { programmerErrorHandler } from 'oops-error'
...
export const doSomething = (params) => {
somePromiseFunction().catch(programmerErrorHandler('failed to do something', {params}))
}
It marks the error as programmer error, adds 'failed to do something' as error message and adds the params as a context (for debugging later)
For errors that we know that can come up (person not found, validEmail, etc) we do something like
import { Oops } from 'oops-error'
export const sendEmail = (email) => {
if(!isValidEmail(email)) {
throw new Oops({
message: 'invalid email',
category: 'OperationalError',
context: {
email,
},
})
}
...
}
At every level we show the error messages of Operational Errors. So a simple
.cath(e => {
if (e.category == 'OperationalError') {
// handle the gracefully
}
else {
throw e // We will tackle this later
}
}
And at the end of our request in express we have our final error handler, where catch the error, check if its operational and then show the error message, but not the actual context. If its a programmer error we stop the process (not ideal, but we don't want the user to keep messing with broken code)

How to throw an error without throw

So recently I was asked a question :
Is there a way to throw an error without using throw in javaScript ?
As far as I knew about errors, there was only one way to throw an error in JavaScript and that was using throw statement in JavaScript like so :
var myFunc = () => {
// some code here
throw 'Some error' // in a conditional
// some more code
}
try {
myFunc()
}catch(e) {
console.log(e)
}
And not knowing any other way I said No, there is no other way. But now I'm wondering whether I was right ?
So the question is whether or not you can throw a custom error in JavaScript without using throw
Restrictions :
Kindly no using eval , Function.
Don't use throw in your code
Additional :
If you can throw an error without using the word Error
Generators do have a throw method that is usually used to throw an exception into the generator function code (at the place of a yield expression, similar to next), but if not caught it bubbles out of the call:
(function*(){})().throw(new Error("example"))
Of course, this is a hack and not good style, I have no idea what answer they expected. Especially the "no division by zero" requirement is sketchy, since division by zero does not throw exceptions in JS anyway.
If all you want to do is throw an error then just do an invalid operation. I've listed a few below. Run them on your browser console to see the errors (tested on chrome and firefox).
var myFunc = () => {
encodeURI('\uD800'); // URIError
a = l; // ReferenceError
null.f() // TypeError
}
try {
myFunc()
}catch(e) {
console.log(e);
}
function throwErrorWithoutThrow(msg) {
// get sample error
try {
NaN();
} catch (typeError) {
// aquire reference to Error
let E = typeError.__proto__.__proto__.constructor;
// prepare custom Error
let error = E(msg);
// throw custom Error
return Promise.reject(error);
}
}
throwErrorWithoutThrow("hi")
/* catch the error, you have to use .catch as this is a promise
that's the only drawback, you can't use try-catch to catch these errors */
.catch((e) => {
console.log("Caught You!");
console.error(e);
});
I think, if you want to use try...catch blocks, you will need to throw something to get to the catchpart. You can use pretty much everything that fails with an error to do that (like mentioned in the other posts).
If at some point, you want to run-or-die without having to write the throw statement yourself, you can always do an assertion:
const myFunction = () => {
try {
assert.fail();
console.log(`Did not work :)`);
} catch (e) {
console.log(`OK`);
}
};
Of course I would rather try to assert something positive (more Zen), that I need in order to continue.
const myTypeErr = () => `This is a Custom Err Message... \nand it`()
try {
myTypeErr()
} catch(e) {} // caught
myTypeErr() // Uncaught TypeError: "This is a Custom Err Message...
// and it" is not a function

Flowtype function can throw error

Is there any way to define that a function explicitly can throw, obviously any function can throw an error. But I'd like to explicitly define that a function is designed to throw and possibly not return a value at all.
async function falseThrow (promise: Promise<any>, error): any {
let value: any = await promise
if (!value) throw error
return value
}
As Nat Mote highlighted in her answer, there's no way of encoding checked exceptions in flow.
However, if you're open to change the encoding a bit, you could do something equivalent:
async function mayFail<A, E>(promise: Promise<?A>, error: E): E | A {
let value = await promise
if (!value) {
return error
}
return value
}
Now flow will force the user to handle the error:
const p = Promise.resolve("foo")
const result = await mayFail(p, Error("something went wrong"))
if (result instanceof Error) {
// handle the error here
} else {
// use the value here
result.trim()
}
If you try to do something like
const p = Promise.resolve("foo")
const result = await mayFail(p, Error("something went wrong"))
result.trim() // ERROR!
flow will stop you, because you haven't checked whether result is an Error or a string, so calling trim is not a safe operation.
Flow doesn't support checked exceptions. It makes no attempt to model which functions may throw or what sorts of errors they may throw.

Categories