JSON fail and continue code - javascript

I am pulling json from an external website. I grab a string with this code from their JSON as I parse it:
breweryName = data.data[i].breweries[0].name;
The problem is that one of the entries in the JSON I receive does not have a value for breweries[0].name.
How Can I keep executing the code? Despite one bad entry? I tried this:
if(data.data[i].breweries[0].name === "undefined"){
breweryName = "N/A"
}
else{
breweryName = data.data[i].breweries[0].name;
}
That still fails

this first checks if there are breweries at given index i and also if there are nested elements, by checking for the size property; within the inner loop, it checks for the name property with typeof():
if(
typeof(data.data[i].breweries) !== 'undefined' &&
data.data[i].breweries.size > 0
){
/* traverse the individual entries */
data.data[i].breweries.forEach(function(v, i){
if(typeof(v.name) !== 'undefined'){
/* the element has a name property */
} else {
/* name property is absent */
}
});
}
next time please provide some sample data, that makes answering more easy.
because it might be array or object... which requires different treatment.

In JavaScript, use the typeof function
if (typeof data.data[i].breweries === "undefined" ||
typeof data.data[i].breweries[0] === "undefined" ||
typeof data.data[i].breweries[0].name === "undefined")
you may also want to include
if (data.data[i].breweries[0].name.trim() === "")
to check for names that are present, but empty.
A shortcut approach may work as well ...
breweryName = data.data[i].breweries[0].name || "N/A"

Related

Efficient way to calculate if the fields are populated using the if condition in javascript when the field list is very large

I have a form which has lot of fields consider maybe 100. All of the fields are different such as it could be StartTime DateTime EndTime Value etc.. User can fill whichever the field they want and keep the remaining fields black.
Now on the Javascript or Node.js side I need to check if the fields are populated for each of them then based on that I need to create an XML file. As of now, I am trying to check if each field is populated using the if the condition. If I proceed in this method then I need to write 100 IF condition to manage all 100 fields which are time-consuming and redundant.
I was just curious if there is any better way of doing it. I tried searching but could not find any relevant post which gives me some sort of idea. If it's duplicate then I am really sorry.
Does anyone have a better idea?
As of now, I am checking something like this:
if(StartTime != '' && StartTime != null && StartTime != undefined)
{
append(StartTime)
}
if(DateTime != '' && DateTime != null && DateTime != undefine)
{
append(DateTime)
}
if(EndTime != '' && EndTime != null && EndTime != undefine)
{
append(EndTime)
}
if(Value != '' && Value != null && Value != undefine)
{
append(Value)
}
.
.
.
.
You could do something like this
const appendIf = () => {
if(val != '' && val != null && val != undefine) {
append(val);
}
};
appendIf(StartTime);
appendIf(DateTime);
appendIf(EndTime);
appendIf(Value);
If all the values are in an array or object, you could also just loop over that:
for(/* whatever for loop is needed*/) {
appendIf(currentValue);
}
I would suggest using a data structure where you can save the data you want to check on, and also if you're checking the same condition for every field then implement the logic in a function. Assuming you're using an array as the data structure the code would look like this:
const appendField = (field) => {
if (field != '' && field != null && field != undefined)
//here you can do something in this case append(field)
}
// myArr is the array where you have the data you want to check
myArr.forEach(field => appendField(field))
Looping over the keys in the object and checking the value for each unique key could be a good way to go. If you need to maintain the order of the keys, the forEach method allows you to pass in an index as well. i in the example.
const appendValues = (data) => {
const keys = Object.keys(data);
keys.forEach((key, i) => {
if (data[key]) {
// Append logic if value
append(data[key]);
} else {
// Logic if no value
}
})
};

How to use promises to continue operation

I need to search a large JSON file for an id and return all the attributes. However, there is a parentId attribute. This corresponds to the id of another object whose attributes I need to include, and possibly another parentId, etc.
m.getAttrs = function(o){
var a = []
// get the model based on id or object.id
if(o instanceof String)
var obj = json.models.filter(i => i.id == o)[0]
else
var obj = json.models.filter(i => i.id == o.id)[0]
////// On 2nd iteration: "TypeError: Cannot read property 'hasOwnProperty' of undefined" ///////////////
if( obj.hasOwnProperty("parentId") && obj.parentId != ""){
// get parent id
var pid = obj.parentId
// get parent attributes
a.push(m.getAttrs(pid)) // RECURSION //
}
// get attributes
var attrs = obj.attrids
// get Attribute Names
for(aid in attrs){
var aName = json.attrs.filter(i => i.id == aid)
a.push(aName)
}
return a
}
I'm seeing an error where obj is not defined after the first iteration of getAttrs. I think this is because json.models.filter... isn't finished, but it could be a lot of things.
I've tried a bunch of times to implement promises, but can't seem to get anything working, and it makes my code too messy for me to want to include it here.
How can I implement a promise to say "after you find the right model, CONTINUE (rather than execute another function)"?
Here's what I found out...
According to Jamiec, It is not possible to use a promise to continue regular operation. Although it seems like a generator may be able to accomplish this, but I'm not familiar with them.
Array.prototype.filter is synchronous, so my issue wasn't with async in the first place. It turns out that instanceof String doesn't work unless you specifically make a String variable. Here's a post I found to help with that: Why does instanceof return false for some literals?
This fixed my code:
if(typeof o === "string")
var obj = json.models.filter(i => i.id == o)[0]
else
var obj = json.models.filter(i => i.id == o.id)[0]

Why am I getting an undefined error from this jquery?

I'm trying to ensure there is always an image with a personal bio. There could be two images or none available to use (coming in from Xpath Parser feed). If no image is found in the XML, I want to load a default placeholder. Console tells me this line "Uncaught TypeError: Cannot read property 'indexOf' of undefined". I've tried many things to fix it but not having any luck. Any advise is appreciated.
if ($('.a_class').attr('src').indexOf('jpg') == -1
&& $('.b_class').attr('src').indexOf('jpg') == -1) {
$('.a_class').attr('src', '/folder/default_img.JPG');
}
First off, running the same jQuery selector multiple times is expensive. In my experience, saving the selector makes the Javascript visibly more responsive:
var aClass = $('.a_class');
var bClass = $('.b_class');
According to jQuery's attr(attributeName) documentation, it can return undefined if the attribute is not set, so you have a few things to check in your if condition. I'd also cache the result of attr(attributeName) in a variable:
var aClassSrc = aClass.attr('src');
var bClassSrc = aClass.attr('src');
This should finally work:
if ((typeof aClassSrc === "undefined" || aClassSrc.indexOf('jpg') == -1)
&& (typeof bClassSrc === "undefined" || bClassSrc.indexOf('jpg') == -1)) {
aClass.attr('src', '/folder/default_img.JPG');
}
Note that we're assuming a_class and b_class exist somewhere in the part of the DOM you're searching, and they exist once. If they don't exist, the attr(attributeName) calls won't do anything without warning. Additionally, if there are multiple a_class or b_class elements, the attr call that sets the "src" tag will set it for every a_class element. Make sure you are OK with this.
I used javaJake's answer as the foundation to write the rest of the necessary logic to hopefully make this work completely (see below). The code does not invoke any errors in the console. However, I have discovered that something (in the CMS) is hard-coded to override the javascript I'm adding to the page so I don't actually know if this works yet. Unless you see something glaringly obvious wrong with the code, I guess there is no point in responding just yet. I am looking into what is doing the override and will update the post when I do. I want to thank everyone for their help, comments, and suggestions thus far.
<script>
var aClass = $('.a_class');
var bClass = $('.b_class');
var cId = $('#c_Id');
var aClassSrc = aClass.attr('src');
var bClassSrc = bClass.attr('src');
// set default if nothing is returned in XML
if ((typeof aClassSrc === "undefined" || aClassSrc.indexOf('jpg') == -1) && (typeof bClassSrc === "undefined" || bClassSrc.indexOf('jpg') == -1)) {
cId.attr('src', '/folder/imagefield_default_images/bio_default_photo.JPG');
}
// if two images are returned, use aClass and hide bClass
else if ((typeof aClassSrc === "undefined" || aClassSrc.indexOf('jpg') >= 0) && (typeof bClassSrc === "undefined" || bClassSrc.indexOf('jpg') == 0))
$('.b_class').hide();
// if aClass is not preset, use bClass and hide aClass's broken image URL icon
else if ((typeof aClassSrc === "undefined" || aClassSrc.indexOf('jpg') >= -1) && (typeof bClassSrc === "undefined" || bClassSrc.indexOf('jpg') == 0))
$('.dm_image').hide();
</script>

Check if nested object is declared and has a value without so many conditional checks

I have a JSON object which I get from a server. The key which I get the value from looks something like this:
var myJson = data.body.region.store.customer.name;
I am trying to get the name key here, but sometimes the JSON (which comes from a service I have no control over) will have some empty fields, like for instance name might not be defined so the object will actually look like this: data.body.region.store.customer. Sometimes too customer, or store, or region might not be defined (If the data doesn't exist the service doesn't return a null or empty string for the value).
So if I need the name what I am doing is this:
if(data.body.region.store.customer.name){
//Do something with the name
}
But say even store isn't defined, it will not get the value for name(which I would expect to be undefined since it doesn't exist) and the program crashes. So what I am doing now is checking every part of the JSON before I get the value with AND operands:
if(data && data.body && data.body.region && data.body.region.store && data.body.region.store.customer && data.body.region.store.customer.name){
//Do something with the name value then
}
This works, because it checks sequentially, so it first checks does data exist and if it does it checks next if data.body exists and so on. This is a lot of conditions to check every time, especially since I use the service a lot for many other things and they need their own conditions too. So to just check if the name exists I need to execute 6 conditions which of course doesn't seem very good performance wise (and overall coding wise). I was wondering if there is a simpler way to do this?
var myJson = null;
try {
myJson = data.body.region.store.customer.name;
}
catch(err) {
//display error message
}
You can try following
function test(obj, prop) {
var parts = prop.split('.');
for(var i = 0, l = parts.length; i < l; i++) {
var part = parts[i];
if(obj !== null && typeof obj === "object" && part in obj) {
obj = obj[part];
}
else {
return false;
}
}
return true;
}
test(myJson, 'data.body.region.store.customer.name');

Checking textbox if it's empty in Javascript

I wrote a simple html file with a textbox and submit button, and it generates and document.write's a response dependant on what you submit. I want to have it generate a response saying to enter content if the box is empty. The textbox's id is chatinput, so I have the following the code in the beginning
var chatinput_box=document.getElementById('chatinput');
var chatinput=chatinput_box.value;
Then a have a conditional, although I can't get it to work correctly; I've tried
if(chatinput==""){}
if(chatinput.length=0){}
if(chatinput=null){}
and others but none have worked correctly. Does anyone have another idea?
It should be this:
var chatinput = document.getElementById("chatinput").value;
if (chatinput == "" || chatinput.length == 0 || chatinput == null)
{
// Invalid... Box is empty
}
Or shorthanded:
if (!document.getElementById("chatinput").value)
{
// Invalid... Box is empty
}
The = assigns a value whereas == checks whether the values are equal.
Just offering an alternative, not trying to steal thunder ...
Create an isEmpty function to reuse on a variety of items.
function isEmpty(val){
return ((val !== '') && (val !== undefined) && (val.length > 0) && (val !== null));
}
Then you can apply it to whatever element you want:
if(!isEmpty(chatinput)){
// hooray its got a value!
}
Not exactly original, its the concept stolen from PHP, but it comes in handy a lot.

Categories

Resources