Reputation: 2098
Inside a callback I build an object I build to send out in my Express app:
this.response = {
owner: data.actions[1].causes[0].shortDescription,
build_version: data.actions[0].parameters[0].value,
branch_to_merge: data.actions[0].parameters[1].value,
jira_tickets: data.actions[0].parameters[2].value,
build_description: data.actions[0].parameters[3].value,
outcome: data.result
};
If I get a different response than what I'm used to I get a fatal cannot find 'property' of undefined
error that crashes my server caused by these: data.actions[1].causes[0].shortDescription
.
I was wondering what to do about it and I thought I could just put it in a try catch
but that seems wrong.
What's considered a good way of dealing with this?
Upvotes: 6
Views: 1328
Reputation: 7736
In your statement you have:
That's what try/catch handles best. Dealing with the same type of error from a block of code and handling in one place. So unless you want to deal with each potential error individually, try/catch is the simplest and best tool you at your disposal. It works and you can pinpoint the problem:
var w = {}
try {w.x.y.z} catch(e) {e}
TypeError: Cannot read property 'y' of undefined(…)
Alternatively, if you need more control, you could
If it must succeed even if some properties fail, you can check each reference. e.g.:
var sdValid = data &&
data.actions &&
data.actions.length>1 &&
data.actions[0].causes &&
data.actions[0].causes.length &&
data.actions[1].causes[0].shortDescription;
var owner = sdValid
? data.actions[1].causes[0].shortDescription
: 'default value';
this.response = {
owner : owner,
// etc...
}
You can easily make it more readable if you
this.response = {
owner : nestget(data, 'nobody')
.prop('actions', 1)
.prop('causes', 0)
.prop('shortDescription')
.value(),
// return shortDescription if you got this far or 'nobody'
build_version : nestget(data, '0.0.0')
.prop('actions', 0)
.prop('parameters', 0)
.prop('value')
.value(),
// return value if you got this far or '0.0.0'
// ... etc
};
// Custom - easy to use reference checker
function nestget (obj, default) {
var valid = false;
this.default = default;
this.obj = obj;
var that = this;
return {
prop : propChecker,
value : getValue
}
function propChecker (prop, i) {
// implementation omitted for brevity
}
function getValue () {
return value;
}
}
Last but not least, you can always use a library. Personally I like how XPath searches XML trees so I would suggest using something like JSONPath to search for nested objects in a data structure. e.g.
this.response = {
owner : jsonpath(data, '$..shortDescription[0]'),
build_version jsonpath(data, '$.actions[0].parameters[0].value'), // no error
// ... etc
}
However, there are lots of options out there (e.g. lodash/underscore as mentioned in a comment).
Upvotes: 2
Reputation: 401
try {
//unwrap your data
}
catch(err) {
//handle the failure
}
is a good solution, depending on how nuanced you want to be
If you want to continue with execution even if one or more is failed, you might consider the conditional assignment operator
javascript: is this a conditional assignment?.
this.response = {
owner: data.actions[1].causes[0].shortDescription || undefined,
etc: data.something || undefined
};
Of course, you will have to make sure the stuff that handles this.response upstream is not going to blow up for the same reason.
Edit: The above is not working for me, though I thought it was a feature of javascript. If you can't get it to work, you can accomplish the same thing with the ternary operator
var asdf = (jkl == undefined) ? 3 : jkl;
Which says
if(asdf == undefined) asdf = 3; else asdf = jkl
The trouble with this is that if you do
var asdf = (nested.variable == undefined) ? 3 : nested.variable;
Your code will break if nested
is undefined
. There are a few workarounds to this, such as setting a number of flags and then conditioning your ternary on those.
I've heard (and agree) that nested ternary statements is not a very good idea.
Another edit:
Check over here How to determine if variable is 'undefined' or 'null'? for issues regarding variables that may or may not be defined.
Apparently == undefined
and == null
only work if the variables are declared but not defined.
Which actually, I think that is the case for you. When in doubt though, use typeof
.
Upvotes: 0