I have tried for a couple of days researching on how to create a custom exception in a try/catch.
Here is what I am attempting to do:
I have an included JS file in my html page. The JS file defines a custom object, as well as defining methods for the object.
Next, in the html page I am doing the following:
try {
MyObj = new CustomObj; //from the included JS file.
MyObj.CustomMethod(); //also from the included JS file.
} catch(e) {
alert("Error in either the create of the object, or the method. Error is " + e.description)
}
I need to be able, within the code for the CustomMethod(), to set the Error Object's properties that are captured in the catch statement. For example:
CustomMethod = function{
try{
document.getelementById("field1").value = "my value";
} catch(err) {
//Set the return error
ReturnErr.description = "There was an error!";
}
};
Can this be done? From what I have tried, I have used the throw statement, but it does not effect the Error Object, thus the catch section is never triggered. In face, the custom message is only shown in the Console.
Thanks ahead of time.
Try:
function MyException(_message, _data) {
this.message = _message;
this.data = _data;
this.name = "MyException";
}
Usage
try{
//...
}
catch(_error){
throw new MyException(message, _error);
}
Hope it will help you to sort things out
Related
Just wondering if we are able to re-write data that we was set via the setWriteString() method while responding to an inbound api call. For example, let's say the scripted rest resource code is as follows:
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
var body = request.body.data;
/* do something with request data
..
..
..
then start preparing the response
*/
var writer = response.getStreamWriter();
try
{
response.setContentType('application/json');
response.setStatus(200);
writer.writeString("{\"results\":[");
var inc = new GlideRecord('incident');
inc.query();
while(inc.next()){
var obj = {};
obj.id = inc.getValue('number');
obj.sys_id = inc.getUniqueValue();
writer.writeString(global.JSON.stringify(obj));
if (inc.hasNext()) {
writer.writeString(",");
}
}
writer.writeString("]}");
}
catch (ex)
{
// let's say exception was thrown on the 3rd iteration while gliding the incident table
// oh no...an exception..so we need to write something else to the stream
// is it possible to erase/remove everything that was added to the stream up until the exception occured?
// so that the response will contain details only about the error?
// something like below:
response.setContentType('application/json');
response.setStatus(500);
writer.writeString("{\"error\":\"Something went wrong\"}"); // this isn't working btw...the stream contained both the content generated in "try" block as well as the "catch" block
// this should not contain anything related to whatever was written from the earlier iterations....
}
})(request, response);
For the errors you can use the Scripted REST API Error objects.
Which should reset the output stream.
https://developer.servicenow.com/dev.do#!/learn/courses/paris/app_store_learnv2_rest_paris_rest_integrations/app_store_learnv2_rest_paris_scripted_rest_apis/app_store_learnv2_rest_paris_scripted_rest_api_error_objects
(function run(request, response) {
try {
...
} catch (e) {
var myError = new sn_ws_err.ServiceError();
myError.setStatus(500);
myError.setMessage('Something went wrong');
myError.setDetail('Error while retrieving your data: ' + e);
return myError;
}
})(request,response);
It might also be useful to get the error message from the GlideRecord
gr.getLastErrorMessage();
// something like aborted by businessrule or acl, etc...
For the details of your error message.
I am working on a Google Data Studio community connector, and I am trying to display only one field to start with. All of the code is in the code.gs file, except getAuthType() and isAdminUser() is in Auth.gs.
The issue is that once getData() is called, getFields() returns an empty object. Here is the log:
It looks like getSchema() is working correctly, here is the log from that function:
Here is the getFields() function:
function getFields() {
var fields = cc.getFields();
var types = cc.FieldType;
fields
.newDimension()
.setId('device')
.setName('Device')
.setType(types.TEXT);
return fields;
}
Here is getData():
function getData(request){
console.log('getData request', request);
request.configParams = validateConfig(request.configParams);
console.log('getFields()', getFields(), typeof getFields());
var requestedFields = getFields().forIds(
request.fields.map(function(field){
return field.name;
})
);
try{
console.log('start request');
var apiResponse = fetchDataFromApi(request);
var data = formatData(apiResponse, requestedFields);
}catch (e){
cc.newUserError()
.setDebugText('Error fetching data from API. Exception details: ' + e)
.setText(
'The connector has encountered an unrecoverable error. Please Try again later.'
)
.throwException();
}
return {
schema: requestedFields.build(),
rows: data,
}
}
getSchema():
function getSchema(request){
var schema = {schema: getFields().build()};
console.log(schema);
return schema;
}
The community connector is initialized outside of all functions in the same file:
var cc = DataStudioApp.createCommunityConnector();
I looked through the documentation, but I cannot find anything that would cause getFields() to return an empty object, based off what I have. Any thoughts?
I thought that getFields() returning an empty object was causing my app to display the fields incorrectly, but the issue was that the data I was passing to the app was in the incorrect format.
getFields() isn't useful until it is called with build() (i.e. getFields().build() )
I think it is expected behavior to receive an empty object for getFields() alone.
I am new to node.js and I have a simple function which takes to parameters and returns the result of adding those to up:
function DoMath(p1, p2) {
try {
return p1 + p2;
} catch (exception) {
return "sorry, worng output do you want to try again?"
}
}
This function is located it the file app.js.
I also added export of the function: module.exports.DoMath=addTowPharmetrs;
In other file, called app2.js, i am trying to give to parameters to the function and call it:
var key=require("./app.js");
var output=key.addTowPharmetrs(5, 1);
/*expected output: 6*/
console.log(output);
However, the program is not running with the error:
ReferenceError: addTowPharmetrs is not defined
What should I do in order to fix it and make it work?
You mixed up the property name with the local variable name:
module.exports.DoMath=addTowPharmetrs;
should be
module.exports.addTowPharmetrs = DoMath;
I have made a following custom logs function to print all console log messages. Using this function I can control with a single flag variable to either print or not logs throughout the app.
var Utilities = {
showLogs: true,
printLog: function (msg) {
if (this.showLogs) {
console.log(msg);
}
}
};
and I call it as:
Utilities.printLog("a message to print on console");
It works fine as expected. But it has one limitation i.e. its not showing the correct line no# and file name where this was called to print the logs.
One solution is to provide extra parameters to print line no# & file name along with the message.
for instance:
Utilities.printLog("a message to print on console", "10","common.js");
Utilities.printLog("a message to print on console", "310","myLib.js");
I dont want these extra parameters and like to know if there is another option available.
Update:
I tried the V8's Stack Trace API http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi but it only helps in cases when an exception is generated inside try catch block.
First override the Error.prepareStackTrace and create a tracing function like this:
Error.prepareStackTrace = function(error, stack) {
return stack;
};
function getTrace(e) {
var stack = e.stack;
var trace = "";
for (var i = 0; i < stack.length; i++) {
trace += "\r" + stack[i];
}
return trace;
}
and created two sample js files.
libObj.js
var libObj = {
getCube: function(x){
return mathLib.cube( x );
}
};
mathLib.js
var mathLib = {
cube: function(x){
return evilObj * x * x; //see the undefined evilObj --- lets catch trace here
}
};
Now from a third js file (or in my case inside the HTML file) I call the function within the try catch block to see the precise trace of the vulnerable code.
<script type="text/javascript">
try {
var results;
results = libObj.getCube(2);
console.log( results );
} catch (e) {
console.log( getTrace(e));
}
</script>
Now I get below trace of the vulnerable code:
Note:- If you do not override the Error.prepareStackTrace then it gives, I think pretty formatted trace...though both have same info.
Without overriding Error.prepareStackTrace:
Now the question remains open, how I can capture similar trace for my custom logs function as defined above.
You could do this:
var Utilities=
{
showLogs:true,
printLog:function(msg){
if(!this.showLogs) return 0;
var k=new Error().stack.split("\n").slice(2);
k.unshift(msg);
console.log(k.join("\n"));
}
}
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