Try/catch oneliner available? - javascript

Just as you can convert the following:
var t;
if(foo == "bar") {
t = "a";
} else {
t = "b";
}
into:
t = foo == "bar" ? "a" : "b";
, I was wondering if there is a shorthand / oneline way to convert this:
var t;
try {
t = someFunc();
} catch(e) {
t = somethingElse;
}
Is there a method of doing this in a shorthand way, preferably an oneliner? I could, of course, just remove the newlines, but I rather mean something like the ? : thing for if.
Thanks.

You could use the following function and then use that to oneline your try/catch. It's use would be limited and makes the code harder to maintain so i'll never use it.
var v = tc(MyTryFunc, MyCatchFunc);
tc(function() { alert('try'); }, function(e) { alert('catch'); });
/// try/catch
function tc(tryFunc, catchFunc) {
var val;
try {
val = tryFunc();
}
catch (e) {
val = catchFunc(e);
}
return val;
}

No, there isn't a "one-liner" version of try-catch besides simply removing all the newlines.
Why would you want to? Vertical space doesn't cost you anything.
And even if you'll settle for removing all the newlines, this, in my opinion, is harder to read:
try{t = someFunc();}catch(e){t = somethingElse;}
than this:
try {
t = someFunc();
} catch(e) {
t = somethingElse;
}
What you have is perfectly fine. Readable code should be a priority. Even if it means more typing.

There is one liner available as npm package try-catch. You can use it this way:
const tryCatch = require('try-catch');
const {parse} = JSON;
const [error, result] = tryCatch(parse, 'hello');
There is similar approach for async-await try-to-catch:
const {readFile} = require('fs').promises;
read('./package.json').then(console.log);
async function read(path) {
const [error, data] = await tryToCatch(readFile, path, 'utf8');
return data || error.message;
}
All this wrappers do is wrap one function with try-catch block and uses destructuring to get result.
Also there is an idea to use something similar to Go style error handling:
// this is not real syntax
const [error, result] = try parse('hello');

You can get it down to two lines.
try { doSomething(); }
catch (e) { handleError(); }
Or, in your specific example, 3 lines.
var t;
try { t = doSomething(); }
catch (e) { t = doSomethingElse(); }
Either way, if your code allows for it, a two liner is much more concise, IMO, than the typical try/catch block.

While this doesn't help with your question about shorthand, it could help if you are seeking to get a try-catch working in an inline context which expects an expression (as distinct from statements, as try-catch uses).
You can achieve this by wrapping the try-catch into an IIFE, which, though an expression, lets you add statements within it that are immediately executed:
var t, somethingElse;
var failingCondition = false;
var result = failingCondition || (function () {
try {
t = someFunc();
} catch(e) {
t = somethingElse;
}
})();
The above is probably of little use but you could conditionally return values also:
var t, somethingElse;
var failingCondition = false;
var result = failingCondition || (function () {
try {
t = someFunc();
return 'someFunc';
} catch(e) {
t = somethingElse;
return 'somethingElse';
}
})();
Since someFunc() fails here (in our case, since it is not defined), result will equal "somethingElse".

Here it is using only js:
const result = (()=>{ try{ return fn(); } catch(e) { return "other"; } })();
const badFn = ()=>{ return JSON.parse("broken json"); }
const result = (()=>{ try{ return badFn(); } catch(e) { return "other"; } })();
console.log(result);

Related

Avoiding a global variable

The purpose of the example code below is to be able to restrict a function from printing something via console.log (a loop in this case) if the function is executed twice.
However, the function uses the global variable "condition" and I want to find a way to avoid this. I've been playing around with workarounds, but to no avail. Also, I have checked sources online, but relate to other more complex examples which are beyond my level. This is a simpler example, but haven't been able to crack this.
Grateful for some guidance. Thanks.
let condition = false;
const testFunc = function (value) {
for (let i = 0; i < 10; i++) {
if (!condition) {
console.log(value + i);
}
}
condition = true;
};
testFunc(5);
testFunc(5);
The usual answer is to create yet another scope to hold the state:
function once(fn) {
let called = false
return function(...args) {
if (!called) {
fn(...args)
called = true
}
}
}
const test = once(function() {
console.log('hello')
})
test() // hello
test() // nothing
Thanks for your feedback - I considered the use of using closure by way of returning a function within another.
Would this be a viable option in order to avoid a global variable? Note that "func" needs to be declared globally -
const testFuncEncaps = function (value) {
let trueOrFalse = false;
return function () {
for (let i = 0; i < 10; i++) {
if (!trueOrFalse) {
console.log(value + i);
}
}
trueOrFalse = true;
};
};
let func = testFuncEncaps(5);
func();
func();

What is the purpose of return statement in function decorator

I'm learning about decorators and I don't understand one thing - in every example, I came across there was a return statement at the end of a function. What is the purpose of that return statement? From my point of view, it's unnecessary, it doesn't even return anything.
console.log('Hello, ' + name);
}
function loggingDecorator(wrapped) {
return function() {
console.log('Starting');
const wrapper = wrapped.apply(this, arguments);
console.log('Finished');
return wrapper; // Why do I need this?
};
}
const wrapped = loggingDecorator(doSomething);
wrapped('Rita');
const test = wrapped('Rita');
console.log(test); // undefined
Without it, your decorator wouldn't forward along the return value from the wrapped function. Your doSmething doesn't return anything, so this behavior isn't being used, but if you tried to wrap a different function it would be needed.
function doSomethingWithReturn(value) {
return value.toUpperCase();
}
function loggingDecorator(wrapped) {
return function() {
console.log('Starting');
const wrapper = wrapped.apply(this, arguments);
console.log('Finished');
return wrapper;
};
}
const wrapped = loggingDecorator(doSomethingWithReturn);
const test = wrapped('Rita');
console.log(test); // 'RITA', but only because of the `return wrapper` statement

return a return in javascript

I want to write a assert() function in Js. Something like this:
assert = function(condition, message) {
if(condition) {
console.log(message);
} else {
return return;
}
}
But it's not true.
We can write it like this:
assert = function(condition, message) {
if(condition) {
console.log(message);
return true
} else {
return false;
}
}
And use that like this:
function () {
if(!assert(condition)) { return; }
//Other Lines
}
But it could be better if we were be able to use that like this:
assert(condition, 'OK');
Is it possible to return a return?
In fact have we any way to use something like to previous line to end a function by a assert?
Update:
My goal is end a function by a simple assert(condition) use, and not
with use second conditions like if(!assert(condition)) { return; }.
p.s: I'm a newbie.
How about throwing an exception from assert if not true and otherwise nothing. That way, you can use them as you might be familiar already from other languages.
Code example:
assert = function(condition, message) {
if(condition) {
console.log(message);
} else {
throw "Assertion failed!";
}
}
It seems to me you just want to write less code. If you want to write lots of asserts then consider having a function that processes your list for you, then you only need to maintain an array of parameters:
var list = [
[condition, 'OK'],
[condition2, 'OK'],
[condition3, 'OK'],
[condition4, 'OK']
];
function runAsserts(asserts){
for(var i = 0; i < asserts.length; i++){
if(!assert(asserts[i][0], asserts[i][1])) {
return;
}
}
}
Then you just call it with:
runAsserts(list);

How can I detect I'm inside an eval() call?

Does there exist a string s such that
(new Function(s))();
and
eval(s);
behave differently? I'm trying to "detect" how a string is being evaluated.
Check for the arguments object. If it exists, you're in the function. If it doesn't it has been evaled.
Note that you'll have to put the check for arguments in a try...catch block like this:
var s = 'try {document.writeln(arguments ? "Function" : "Eval") } catch(e) { document.writeln("Eval!") }';
(new Function(s))();
eval(s);
Demo
Solution to nnnnnn's concern. For this, I've edited the eval function itself:
var _eval = eval;
eval = function (){
// Your custom code here, for when it's eval
_eval.apply(this, arguments);
};
function test(x){
eval("try{ alert(arguments[0]) } catch(e){ alert('Eval detected!'); }");
}
test("In eval, but it wasn't detected");​
The current answer does not work in strict mode since you can't redefine eval. Moreover, redefining eval is problematic for many other reasons.
The way to differenciate them is based on the fact that well... one of them creates a function and what doesn't. What can functions do? They can return stuff :)
We can simply exploit that and do something with return:
// is in function
try {
return true;
} catch(e) { // in JS you can catch syntax errors
false; //eval returns the return of the expression.
}
So in example:
var s = "try{ return true; }catch(e){ false; }";
eval(s); // false
Function(s)(); // true
(new Function(s))(); // true, same as line above
(function(){ return eval(s); })(); // the nested 'problematic' case - false
evaled code can be detected by invoking an error and checking if the native stack-trace contains a lower row/column indicator.
if (typeof window === 'object') {
// browser
window.isEvilEval = function () {
return parseInt(String(new Error().stack).split(':').pop(), 10) < 10;
};
} else {
// nodejs (must be global to be callable from within Function)
global.isEvilEval = function () {
return (
new Error().stack
.split('\n')
.filter((l) => l.trim().startsWith('at eval') && l.indexOf('<anonymous>:1') > -1).length > 0
);
};
}
// test - directly in code => false
console.log(isEvilEval());
// test - in evil eval => true
eval('console.log(isEvilEval())');
// test scoped in function => false
Function('console.log(isEvilEval())')();

Is there a way to view the call stack dynamically in javascript?

a general question, but the code in question is this:
have an error routine that is thrown to - handles exeptions:
MyObj.prototype.err = function( msg ) { ... throw(msg); }
so to throw,
if( mybad ) this.err( 'my message' );
would like err() to behave differently depending on whether a function is or is not in the call stack.
for example, could be
funcA() -> func2() -> func3() -> err()
versus
funcB() -> func3() -> err()
if funcA were upstream, would like to alert the user and stop; whereas if funcB, would like to write the message to console and continue.
realize other ways to solve the problem, but imho bad luck to create (and maintain) state space that can be deduced from the environment
I'm not sure what you are trying to solve, but I am pretty sure there is a better way to do it than this.
That being said, here's one way of tracing functions and checking the callstack without resorting to parsing of browser-specific stack traces:
var callstack = [];
function traced(name, func) {
return function () {
callstack.push(name);
func.apply(this, arguments);
callstack.pop();
}
}
and use it like this:
var a = traced("a", function () {
b();
});
var b = traced("b", function () {
c();
});
var c = traced("c", function () {
var s = callstack.join("<br>");
document.getElementById('output').innerHTML = s;
});
document.getElementById('a').onclick = a;
document.getElementById('b').onclick = b;
You can check it out on fiddle here: http://jsfiddle.net/AsrSp/
In Chrome you could do:
var err = function( msg ) {
// ...
var error = new Error();
var stack = error.stack;
// Do some string manipulation with stack
// mayThrow = 'funcB is in stack'
if (mayThrow) {
throw(msg);
}
};
May I point out that I consider this a very bad practice. I think you should catch the error in FuncB in stead of defining FuncB as a function not to throw from in err. It is less code and much easier to manage. So:
var err = function( msg ) {
// ...
throw(msg);
};
var func3 = function() {
// ...
err('Double rainbow');
};
var funcB = function() {
try {
func3();
catch(e) {
console.log(e);
}
};
Try to understand why this is the better solution, it is about defining responsibilities for which functionality belongs to which function. This is exactly why exception and handling is designed the way it is.

Categories