I try to create a function that returns values from the server, if one of the values returns with an error then everything that comes back to me from the function falls and I get NULL,
If I use try / catch the problem is solved.
What is the best solution in terms of performance and something that can work in the result I want
public async getUserById(id: number): Promise<dto> {
const arr = [];
const user = await this.userService.getUserById(id);
try {
const company = await this.companyService.getCompanyIdToken(
user.company_id
);
UsersProvider.setUserCompany(user, company);
for (const space of user.spaces) {
try {
const Response = await this.companyService.getSpaceById(space);
arr.push(Response);
} catch (error) {
console.log(error) **// Here I expect you not to throw an error**
}
}
} catch (error) {
console.log(error) **// Here I expect you not to throw an error**
}
return user;
}
As others have explained, in terms of performance, there isn't really a difference between try/catch and catch.
However, in my experience, try/catch statement are much clearer for peer reviews and maintenance (for error message management), but that is just a personal preference.
Moreover, if getSpaceById() can throw synchronously, then you do have to catch that synchronous exception with try/catch if you ever wish to use the .then() statement (you will get an error if you only use.catch() instead of try/catch). You might as well use the try/catch now before getting an error.
I'm still learning the language, and I'm very curious to know what is the proper way to ensure that either all functions will execute or none when one action requires series of functions to be executed. For example I might have an HTML button that calls some apply() function:
function apply() {
try {
// Check arguments, choose what exactly to do next through some IFs etc...
}
anotherFunction();
}
function anotherFunction() {
try {
// Request data from DB, process data received, update object variables, etc...
}
yetAnotherFunction();
}
function yetAnotherFunction() {
try {
// Update HTML
}
oneMoreFunction();
}
function oneMoreFunction() {
try {
// Update graph
}
}
So the problem here is that if any of the functions in the flow throws an error the rest functions won't do what they should, hence the entire Apply process will be interrupted with some changes applied (let's say HTML is getting updated) but the rest (the graph) is not. I'm curious to know what is the best practice to prevent this behaviour? Yes I'm trying my best to use try {} and check arguments for errors etc, but it looks like I can't foresee everything, I just need some way to tell the code "ensure you can execute all of the functions, in case of any errors, just don't do anything at all". Please advise what can be done here?
You're taking the right path when thinking about try/catch blocks, but notice I used a 'catch' as well. Usually (maybe that is even enforced, I can't remember) you need the catch blocks along with the try.
So your functions could look something like this:
function async myFirstTryCatch() {
try {
// Make your request in the try block
await requestCall();
} catch(error){
// Hey, my http call returned an error
// Deal with the error here. Maybe show a toast, validate a form
// Anything you need to not break the code and have good UX
console.log(error)
}
}
In that same line of thought, you could have each function handle their own try/catch or maybe control that in your apply function, in case some of the chain must continue/stop depending each other.
function apply() {
try {
firstCall();
functionThatRequiresFirstCalltoSucceed();
} catch (error){
//Will catch if either firstCall or functionThatRequiresFirstCalltoSucceed fail
console.log(error)
}
functionThatIndependsFromTheResultAbove();
}
I hope this will help you build your thoughts about error handling in JS :)
IMPORTANT NOTE
If your code enters the catch block, it will consider that the error has been dealt with and will not propagate! Here's an example
function functionThatThrowsError(){
try{
throw new Error('Example Error!');
} catch (error) {
// Error has been dealt with
console.log(error) // Returns "Example Error"
// throw error; <--- Throw the error in the catch block if you need t to propagate
}
}
function wontCatchError() {
try {
functionThatThrowsError();
} catch (error) {
// THE CODE WILL NOT ENTER THE CATCH BLOCK
// SINCE THE ERROR WAS CAUGHT IN THE FUNCTION ITSELF.
// If you need to catch here as well, make sure to throw the error
// in the catch block of the 'functionThatThrowsError'
console.log(error)
}
}
I have seen the three following variants of throwing errors.
var response = await api.call()
.catch((error) => {
throw error;
});
var response = await api.call()
.catch((error) => {
throw Error(error);
});
var response = await api.call()
.catch((error) => {
throw new Error(error);
});
I have tried throw new Error(error) but a chain of async functions passing down the error resulted in:
"Error: Error: Error: Actual error message"
Which of these is recommended?
throw Error(error);
that just works because JS always executes the native constructors as constructors, even if you call them as a function. That's like semicolon insertion, while it works, I would not recommend relying on it because it is confusing and might introduce unwanted side effects. Basically, if everything is working as expected it is the same as:
throw new Error(error);
now that also makes little sense, as you lose the errors stack trace. When an error object gets constructed, a lot of information is collected about how the error happened, which is really useful for debugging. As the error constructor expects a string as the first argument, error gets cast to a string, it is basically:
throw new Error(error.toString());
and by stringifying, you only keep the message and lose everything else. You get back an error that occurs at the line above, which hides the place where it originated from, whereas:
throw error;
just passes the error up, which will preserve all the mandatory information.
For clarity, I personally prefer not to mix thenables and async / await, so I would do:
try {
const response = await api.call()
} catch(error) {
// Some logging, handling, etc.
throw error;
}
If you can't handle the error properly and always rethrow, it is senseless, just don't try to catch it. Handle it somewhere up the call stack, where you can actually handle it.
None of them is recommended. If you can't handle an error, don't catch it. However, if you catch some errors, you should throw the error as is so as to preserve all the debugging information:
somePromise()
.catch(reason => {
if (/* some test about the error */) {
// handles some errors
} else {
throw reason; // <- more on that on #JonasWilms' answer
}
})
I'm using tape and I'm trying to test a couple of functions. My functions throw errors and validate objects. I like throwing errors because then later my promises can catch them. I'm trying to run simple tests and establishing the data argument in all the scenarios to hit each error in the stack. How can I test this function without putting it in a try / catch every time? I see there's two functions in the API t.throws() and t.doesNotThrow(), I've tried them both and even added the extra params like t.throws(myFunc({}), Error, "no data") but nothing seems to work as expected.
var test = require('tape')
var _ = require('underscore')
function myFunction(data){
if(!data) throw new Error("no data")
if(_.size(data) == 0) throw new Error("data is empty")
if(!data.date) throw new Error("no data date")
if(!data.messages.length == 0) throw new Error("no messages")
data.cake = "is a lie"
return data
}
test("my function", function(t){
t.throws(myFunction({}))
t.end()
}
I have no loyalty to tape, and I have no clue what I'm doing. I just want to simply test functions synchronous that throw exceptions, without a ton of overhead. So if there's a better unit-testing framework for this use case I'd be glad to use it. If tape has this ability I'd love to use it.
Is this how it should be done?
test("my function", function(t){
try{
myFunction({})
t.fail()
}catch(e){
t.pass(e.message)
}
t.end()
})
Seems I cant call the function within the argument of t.throws because it throws the error, duh. I believe this is the correct usage.
t.throws(function(){
myFunction({})
})
Instead of bind as suggested in the comment above, u could use the arrow function like this:
t.throws(() => myFunction({}), 'should throw an exception')
I have a number of functions which either return something or throw an error. In a main function, I call each of these, and would like to return the value returned by each function, or go on to the second function if the first functions throws an error.
So basically what I currently have is:
function testAll() {
try { return func1(); } catch(e) {}
try { return func2(); } catch(e) {} // If func1 throws error, try func2
try { return func3(); } catch(e) {} // If func2 throws error, try func3
}
But actually I'd like to only try to return it (i.e. if it doesn't throw an error). I do not need the catch block. However, code like try {} fails because it is missing an (unused) catch {} block.
I put an example on jsFiddle.
So, is there any way to have those catch blocks removed whilst achieving the same effect?
A try without a catch clause sends its error to the next higher catch, or the window, if there is no catch defined within that try.
If you do not have a catch, a try expression requires a finally clause.
try {
// whatever;
} finally {
// always runs
}
It's possible to have an empty catch block, without an error variable, starting with ES2019. This is called optional catch binding and was implemented in V8 v6.6, released in June 2018. The feature has been available since Node 10, Chrome 66, Firefox 58, Opera 53 and Safari 11.1.
The syntax is shown below:
try {
throw new Error("This won't show anything");
} catch { };
You still need a catch block, but it can be empty and you don't need to pass any variable. If you don't want a catch block at all, you can use the try/finally, but note that it won't swallow errors as an empty catch does.
try {
throw new Error("This WILL get logged");
} finally {
console.log("This syntax does not swallow errors");
}
Nope, catch (or finally) is try's friend and always there as part of try/catch.
However, it is perfectly valid to have them empty, like in your example.
In the comments in your example code (If func1 throws error, try func2), it would seem that what you really want to do is call the next function inside of the catch block of the previous.
I wouldn't recommend try-finally without the catch, because if both the try block and finally block throw errors, the error thrown in the finally clause gets bubbled up and the try block's error is ignored, in my own test:
try {
console.log('about to error, guys!');
throw new Error('eat me!');
} finally {
console.log ('finally, who cares');
throw new Error('finally error');
}
Result:
> about to error, guys!
> finally, who cares
> .../error.js:9
> throw new Error('finally error');
> ^
>
> Error: finally error
No, it is not possible to have try block without catch (or finally). As a workaround, I believe you might want to define a helper function such as this:
function tryIt(fn, ...args) {
try {
return fn(...args);
} catch {}
}
and use it like:
tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);
I've decide to look at the problem presented from a different angle.
I've been able to determine a way to to allow closely for the code pattern requested while in part addressing the un-handled error object listed by another commenter.
code can be seen # http://jsfiddle.net/Abyssoft/RC7Nw/4/
try:catch is placed within a for loop allowing graceful fall through. while being able to iterate through all the functions needed. when explicit error handling is needed additional function array is used. in the even of error and functional array with error handlers element is not a function, error is dumped to console.
Per requirements of stackoverflow here is the code inline [edited to make JSLint compliant (remove leading spaces to confirm), improve readability]
function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }
// ctr = Code to Run <array>, values = values <array>,
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
"use strict";
var cb; // cb = code block counter
for (cb in ctr) {
if (ctr.hasOwnProperty(cb)) {
try {
return ctr[cb](values[cb]);
} catch (e) {
if (typeof eh[cb] === "function") {
eh[cb](e);
} else {
//error intentionally/accidentially ignored
console.log(e);
}
}
}
}
return false;
}
window.alert(testAll([func1, func2, func3], [], []));
If you only want functions 2 and 3 to fire if an error occurs why are you not putting them in the catch block?
function testAll() {
try {
return func1();
} catch(e) {
try {
return func2();
} catch(e) {
try {
return func3();
} catch(e) {
// LOG EVERYTHING FAILED
}
}
}
}
...is there any way to have those catch blocks removed whilst achieving the same effect? As it would seem, no; Javascript requires a try block be followed by either a catch or a finally block.
Having said that, there is a way to use those catch blocks to achieve the effect you want.
// If func1 throws error, try func2 The if throws error condition, is what the catch block is for.
Why remove them when their use is exactly what you are after?
try { return func1(); }
catch {
// if func1 throws error
try { return func2(); }
catch {
// if func2 throws error
try { return func3(); }
catch {
// if func3 throws error
}
}
}
I completely understand why you might not need a catch block, and would find it cleaner to be able to omit it entirely. But I don't think this is one of those situations.
They go together in every language that I know that has them (JavaScript, Java, C#, C++). Don't do it.
Since ES2019 you can easily use try {} without catch {}:
try {
parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}
For more info please reffer to Michael Ficcara's proposal
try & catch are like 2 side of one coin. so not possible without try.
No. You have to keep them.
This actually makes sense since errors shouldn't be silently ignored at all.