Some of you made some awesome javascript courses which I follow eagerly in the adventure to become a better developer.
One of these courses was about EcmaScript6 const and let variables and the Try and Catch statement. So as a curious junior developer I tried it myself by declaring an arrow function in a constant and trying to change the constant:
const userValidation = (userValid) => userValid == true ? "You may enter" : "You may not enter, sorry.";
try {
var userValidation = function(userID) {
//Execute some code which ofcourse will never execute
}
}
catch(err) {
console.log("Woops, something went wrong.");
}
console.log(userValidation(false));
The behaviour which I expected was the error message: "Woops, something went wrong." because I already declared the constant "UserValidation". But that was not what was happening, instead the console just gave the error and dies:
What am I doing wrong?
try, catch statements are used to catch runtime errors, but this SyntaxError is detected while the Javascript is being parsed, before it is run. This is because you are not reassigning the (const) variable here but redefining it with a different identifier (var). If the code were
const userValidation = (userValid) => userValid == true ? "You may enter" : "You may not enter, sorry.";
try {
userValidation = function(userID) {
//Execute some code which ofcourse will never execute
}
}
catch(err) {
console.log("Woops, something went wrong.");
}
without the var identifier, then this would become a runtime error. The code would be attempting reassign the const variable and your catch statement would execute.
Related
I am trying to figure out how to write "this line of code has to produce an exception" in one of my test cases for qml. What I am doing essentially is
TextField{
id: defaultLineEdit
onTextChanged: { throw "test";}
}
then in my test code:
function test_exception(){
try {
defaultLineEdit.text = "text";
}
catch(e){
console.log("caught exception");
}
}
The problem is - I have verified that the exception is thrown on text changed, but I never enter the catch branch somehow. What is happening here?
Here's what I want to accomplish:
check if element "Error" span exists
then do something if it does ===
else check if element "el2" span exists
then do something ====
else
do something
Here's my code
let done = false;
let errorOccured = false;
let isManualStep = false;
do {
try {
console.log('Checking span.label-red=Error...................')
let errorStepExists = $('span.label-red=Error').isExisting();
if (errorStepExists) {
console.log('Error encountered...................')
done = true;
}
} else {
console.log('Error not encountered...................')
let el2Exists = $('span>td.col-md-2=Waiting').isExisting();
if (mel2Exists) {
console.log('Encountered...................')
}
} catch (e) {
console.log(e);
}
}
while (!done);
It doesn't seem to go to the catch block if element doesn't exist and it fails my test instead with a timeout error.
Error: Timeout of 20000ms exceeded. The execution in the test "xxxxxx" took too long. Try to reduce the run time or increase your timeout for test specs (https://webdriver.io/docs/timeouts.html).
Not sure how to best way to achieve your goal in your programming language binding, however the best way in java is to use the "findElements(By locator)" method of WebDriver interface.
This method returns a List. You then check for the existence of your WebElement by examining the size of this list. (If the size is not 0, your WebElement is present).
Hope this helps you come by with a similar approach in your language binding.
I have strange error generation function.. It is from HttpRequest like this
public async request(method, url, data, headers = {}){
let init { method: method };
if (data) {
let payload: string = JSON.stringify(data);
init.body = payload;
}
if (this.key) headers["x-auth-token"] = this.key;
headers["Content-Type"] = "application/json";
init.headers = headers;
let result = await fetch(url, init);
if (result.status == 200) return result;
throw { status: result.status, message: result.statusText };
}
Now, I am trying to catch with something like this:
try {
let img = await HttpRequest.request("GET", "/login");
let text = await img.text();
let str = "data:image/jpeg;base64, " + text;
this.setState({ avatar: str });
} catch (err) {
console.log("log here");
}
What is strange, was that nothing catched, even though I deliberately made an error, no "log here" shows anywhere in console.
But if I change it like this:
try {
let img = await HttpRequest.request("GET", "/login");
let text = await img.text();
let str = "data:image/jpeg;base64, " + text;
this.setState({ avatar: str });
} catch (err) {
console.error("log here"); // <--- console.error() instead of console.log
}
Then the console showed "log here" error. It is strange that difference between console.log and console.error inside same catch clause treated different way.
Can anyone help me here, where did I do wrong?
Thank you
EDIT: If it made difference, the code behaved correctly before, when I throw the error as throw "ERROR " + result.status + ": " + result.statusText; at my request() function. It was back to normal when I changed it back to throw string instead of object.
Well.. I am not sure if this is the answer, or proper answer, but the question turned out not programming or javascript nature.
After I tried Parth Savaliya's comment, I had some ideas, and I tried to make this very simple function
function testError() {
throw {aa: 'test', bb: 'bb'};
}
try {
console.log("nothing here");
testError();
} catch (err) {
console.log(err);
console.log('foo');
}
and every time I feed different object, any console command, including console.error() gave me different result. The previous console.error() was just luck. It was varying from unintelligible mumble jumble, various strings, to no output, and finally crashed Google Chrome. There was no pattern, and seemed random. I also tried to replace console.log() in catch clause with an XHR request to server, and it worked fine. Firefox worked fine. So I conclude that it was chrome's console that was having problem. Tried to remove all extensions, cleaned cache and everything, reinstall chrome, and it was solved.
I think you're currently viewing only error logs, like
this...!
Please click on the first item on the list, to show all types of log, like
this...!
Implementing an assert in javascript is not difficult:
assert = function(expression,errorMessage){
if (!expression){
errorMessage = errorMessage || "(no msg)";
throw new Error("assert failed: "+errorMessage);
}
return true;
};
However, using this version of assert is tiresome because you have to have a meaningful error message for every test case:
var types = {isNumber:function(x){return typeof x === "number" && isFinite(x)}}
assert(types.isNumber(1)===true,"types.isNumber(1)===true");
assert(types.isNumber(NaN)===false,"types.isNumber(NaN)===false");
My question is that is there a way to implement the assert function such that it only takes one expression and it can return meaningful error message if that expression is not met? Like:
assert(SOMETHING_that_is_not_true); // throw Error: SOMETHINGELSE that refers to this particular assertion
assert(SOMETHING_that_is_not_true2); // throw Error: SOMETHINGELSE2 that refers to this different assertion
It's a bit more code than a simple expression for each assertion, but how about this?
assert = function(expression){
if (!expression()){
errorMessage = expression.toString() || "(no msg)";
throw new Error("assert failed: "+errorMessage);
}
return true;
};
assert(function() { return 'b' == 'a' });
I just want to add this as it will work. But it is
Not advised
As it uses eval, which is, juck. But it is useful if you don't face it to the client. (What am I saying? It is not advised. End of that. But it does work.)
function assert(expression){
var success = eval(expression);
if(!success) throw new Error("assert failed: "+ expression);
else return true;
}
Then you can do
assert("types.isNumber(1)===true");
So te reiterate, use #James Thorpe s code (hopefully) above.
Short version
Trying to write a debug command that returns the call stack, minus the current position. I thought I'd use:
try {
throw new Error(options["msg"])
} catch (e) {
e.stack.shift;
throw (e);
}
but I don't know how to do it exactly. apparently I can't just e.stack.shift like that. Also that always makes it an Uncaught Error — but these should just be debug messages.
Long version
I decided I needed a debug library for my content scripts. Here it is:
debug.js
var debugKeys = {
"level": ["off", "event", "function", "timeouts"],
"detail": ["minimal", "detailed"]
};
var debugState = { "level": "off", "detail": "minimal" };
function debug(options) {
if ("level" in options) {
if (verifyDebugValue("level", options["level"]) == false)
return
}
if ("detail" in options) {
if (verifyDebugValue("detail", options["detail"]) == false)
return
}
console.log(options["msg"]);
}
function verifyDebugValue(lval, rval){
var state = 10; // sufficiently high
for (k in debugKeys[lval]) {
if (debugKeys[lval][k] == rval) {
return true;
}
if (debugKeys[lval][k] == debugState[lval]) { // rval was greater than debug key
return false;
}
}
}
When you using it, you can change the debugState in the code to suit your needs. it is still a work in progress but it works just fine.
To use it from another content script, just load it in the manifest like:
manifest.json
"content_scripts": [
{
"js": ["debug.js", "foobar.js"],
}
],
and then call it like:
debug({"level": "timeouts", "msg": "foobar.js waitOnElement() timeout"});
which generates:
foobar.js waitOnElement() timeout debug.js:17
And there is my problem. At the moment, it is using the console log and so all the debug statements come from the same debug.js line. I'd rather return the calling context. I imagine I need something like:
try {
throw new Error(options["msg"])
} catch (e) {
e.stack.shift;
throw (e);
}
but I don't know how to do it exactly. apparently I can't just e.stack.shift like that. Also that always makes it an Uncaught Error — but these should just be debug messages.
You can't avoid mentioning the line in your debug.js, because either using throw (...) or console.log/error(...) your debug.js will be issuing the command.
What you can do, is have some try-catch blocks in your code, then in the catch block pass the error object to your debug function, which will handle it according to its debugState.
In any case, it is not quite clear how you are using your debug library (and why you need to remove the last call from the stack-trace, but you could try something like this:
Split the stack-trace (which is actually a multiline string) into lines.
Isolate the first line (corresponding to the last call) that is not part of the error's message.
Put together a new stack-trace, with the removed line.
E.g.:
function removeLastFromStack(stack, errMsg) {
var firstLines = 'Error: ' + errMsg + '\n';
var restOfStack = stack
.substring(firstLines.length) // <-- skip the error's message
.split('\n') // <-- split into lines
.slice(1) // <-- "slice out" the first line
.join('\n'); // <-- put the rest back together
return firstLines + restOfStack;
}
function myDebug(err) {
/* Based on my `debugState` I should decide what to do with this error.
* E.g. I could ignore it, or print the message only,
* or print the full stack-trace, or alert the user, or whatever */
var oldStack = err.stack;
var newStack = removeLastFromStack(oldStack, err.message);
console.log(newStack);
//or: console.error(newStack);
}
/* Somewhere in your code */
function someFuncThatMayThrowAnErr(errMsg) {
throw new Error(errMsg);
}
try {
someFuncThatMayThrowAnErr('test');
} catch (err) {
myDebug(err);
}
...but I still don't see how removing the last call from the trace would be helpful