Avoid 'Cannot read property of undefined' error when mapping data - javascript

I'm receiving some data back from Google Books API calls and I'm mapping the data into a lighter array I can then work with. I'm using this line to map the data I'm interested into:
data.items.map(function(book) {
return { googleId : book.id, image : book.volumeInfo.imageLinks.thumbnail, authors : reduceAuthors(book.volumeInfo.authors), title : book.volumeInfo.title, subtitle : book.volumeInfo.subtitle, publishedDate : book.volumeInfo.publishedDate, publisher : book.volumeInfo.publisher}
});
Most of the times it works just fine, but some times one of the elements is missing, may it be imagelinks or authors therefore I get this error "Uncaught TypeError: Cannot read property of undefined".
What is the best way to avoid this error?
The only solution I have in mind is to first run a sanity check on the whole data and apply the map only after, but there maybe is a better solution? And wrapping everything in a try and catch throws me out of the mapping operation too early and doesn't complete with the rest of the data.

You can check it inside map() function, without handle previously the entire data. With a ternary conditional , something like this:
image : ((book.volumeInfo.imageLinks) ? book.volumeInfo.imageLinks.thumbnail : undefined)
So if book.volumeInfo.imageLinks is null/empty/undefined there aren't error and the value inserted will be undefined, otherwise catch the thumbnail value.

Related

d3js v6 reading multiple csv with Promise.all returning 404

I am new to working with d3 and loading in data, and I had an error I could not find any solution for.
I am trying to read a few csv files at once, filter them, and allow for them to be used later on with drawing my graphs. Note, the code below is simplified with the datafile names and variable names.
Promise.all([
d3.dsv(";", "data/data1.csv"),
d3.dsv(";", "data/data2.csv"),
d3.dsv(";", "data/data3.csv"),
]).then(function(data) {
var var1 = data[0].filter(d => d => d.Date_statistics.includes("-2-"));
var var2 = data[1].filter(d => d => d.Municipality_name.includes("Amsterdam"));
var var3 = data[2].filter(d => parseInt(d["Total Population"]) > 50000);
console.log("result 1: ", var1)
console.log("result 2: ", var2)
console.log("result 3: ", var3)
}).catch(function(err) {
// handle error here
console.log(err)
});
The problem I am facing, is that when I have added this to my js file, and have that added in my HTML, the console returns to me with a GET error 404, "data/data2.csv" not found(and the same for data3.csv). I'm not sure why I'm getting a 404 error here, because as far as I can tell, I'm loading the data properly as a csv, after which I'm trying to do some filtering to print.
I have tried to make the files that I put in as a variable, and use the path as the value, but that did not work either. Putting all the dsv reading functions with their individual filtering and logging separately, so not in a Promise.all() function, gives me the same result, except for the fact that it now does print the content of the first filtering.
Is there something wrong with how I'm approaching the problem(as in, I should not use Promise.all() here), or am I missing something that results in these 404 errors?
Alright, seems like I've made a mistake after all, my data files had an error in their names when I put them into the d3.dsv(";", "...") part, the names were just not matching up with the names of the actual data files. This can be closed.

Extract from a NODE-RED string

I have my NODE-RED schemma:
following string result from my "Function" node my node:
msg.payload : string[63]
"{"random":{"date":"22:55","random":21},"time":{"time":"22:52"}}"
This is the code of my "Function Node":
msg.payload.random=context.global.randomandtime;
msg.payload.time=context.global.time;
return msg;
I need to put in "part of the string" (not all) like this =>{"date":"22:55","random":21} and show it in my browser like a webpage but not using html tags.
Like this:
22:55
21
Any help will be wellcome.
I have added template(Mustache) and I am traying to bring data to it,(Note:http response is already in schemme but not shown here)
I am traying to bring data here (template). But I get error.
The Mustache template body is:
This is the payload: {{#payload.randomandandtime.random}} !
But I have back this error back:
2017-5-18 16:18:00node: Mustachemsg : string[56]
"Unclosed section "payload.randomandandtime.random" at 59"
In browser I get
502 Bad Gateway: Registered endpoint failed to handle the request.
Even If I change it only payload.randomandandtime I get empty:
payload.randomandandtime
In browser & console:
Messsage received back: (empty)
This is the payload: !
Finally I solved in this way.
I make all in one Global varaible instead 2 global variables.
I passed it to mustache template and in Mustache I worked with context in order to get it.
General Scheme:
Then in recoverydata:
msg.payload = context.global.get("randomtime");
In My Mustache:
`{{#payload.random}}
Last random number request returned {{&payload.random}}, which was received
at {{&payload.randomtime.times}}{{/payload.random}}
{{/payload}}`
The resul of it is a Webservice not using HTML and this is:
url https://....../page
"Time last server time request received at 13:14 Last random number request returned 94, which was received at 13:14"

Reading from JSON returns undefined

I'm trying to read from a JSON that contains my error messages, so that in case I'd ever want to change what my error messages say, I'd just change the JSON instead of diving into my source code. Everything seems to be working fine...
var fs = require('fs')
console.log("Now reading from error messages configuration file...");
var errorMsgs = JSON.parse(fs.readFileSync('config/error_msgs.JSON'));
console.log(errorMsgs)
This is what's in errorMsgs.json:
{
"bad_password" : [
{
"error" : "Incorrect login credentials.",
"details" : "This happens if you either have an incorrect username or password. Please try again with different credentials."
}
],
"missing_fields" : [
{
"error" : "Credentials failed to parse.",
"details" : "This happens when one or more fields are missing (or have illegal characters in them), please try again with different credentials."
}
]
}
When I log to the console, errorMsgs displays fine. When I log one of the items that errorMsgs has (like bad_password), it also works fine, as in it displays the items that are nested inside. However, when I attempt to retrieve a specific value like errorMsgs.bad_password['error'], it returns undefined. I can't seem to figure it out. I tried dot notation (errorMsgs.bad_password.error), which returns undefined. I tried the method above (errorMsgs.bad_password['error']) which also returns undefined. Asking for the typeof of errorMsgs, it returns object, which I assume makes it not a string. Passing the value to a variable first and then logging the variable doesn't do anything either. Is node converting it to a string on-the-fly, causing it to return undefined, or am I just doing something wrong?
bad_password" : [
{
"error" : "Incorrect login credentials.",
"details" : "This happens if you either have an incorrect username or password. Please try again with different credentials."
}
],
Your nested object is contained in an array.
errorMsgs.bad_password[0]['error']
This is what you're looking for. Just grab the first value of the array

Getting an error with Twitter lib

In Google Apps Script I have this snippet of code in my project to send a tweet (also in jsBin):
function sendTweet(status) {
var twitterKeys= {
TWITTER_CONSUMER_KEY: "x",
TWITTER_CONSUMER_SECRET: "x",
TWITTER_ACCESS_TOKEN: "x",
TWITTER_ACCESS_SECRET: "x"
};
var props = PropertiesService.getScriptProperties();
props.setProperties(twitterKeys);
twit = new Twitter.OAuth(props);
var service = new Twitter.OAuth(props);
if ( service.hasAccess() ) {
var response = twit.sendTweet(status);
if (response) {
Logger.log("Tweet ID " + response.id_str);
} else {
// Tweet could not be sent
// Go to View -> Logs to see the error message
}
}
}
sendTweet("test");
But the problem I'm having is that I get this error:
TypeError: Cannot read property "text" from undefined. (line 293, file "twitter", project "Twitter lib")
Line 293 is from version 21 of the "Twitter lib" library (MKvHYYdYA4G5JJHj7hxIcoh8V4oX7X1M_).
The message "test" actually gets tweeted, despite that error. Does anyone know how to fix it?
Hi, author of Twitter Lib here. #Mogsdad pointed me here over Twitter. I think I know what's going on with your script, and it's a peculiarity of how Google Script works.
You have most of your code in a function that takes an argument, and then you have a call to the function at the top level of your script. What happens, when you go to the "Run" menu and select your sendTweet function, is that the script at the top level gets run before the selected function is executed, and the tweet would be sent at that time with the "test" text.
Then after that, sendTweet gets run with no arguments, meaning the status variable is undefined. You're sending an undefined value into twit.sendTweet(), causing the error you see.
What I'd recommend here is simply wrapping your last line of code into a function so you can call it from the Run menu, like this:
function sendTestTweet() {
sendTweet("test");
}
Just to recap, the error you've seen is:
TypeError: Cannot read property "text" from undefined. (line 293, file "twitter", project "Twitter lib")
That is in the sendTweet() method of the library, see below.
/**
* Upload a tweet to Twitter with optional media.
*
* #param {string | Tweet} tweet the status text to send as a Twitter update
* #param {optional object} params any additional parameters to send as part of the update post
* #return {object} the Twitter response as an object if successful, null otherwise
*/
OAuth.prototype.sendTweet = function(tweet, params) {
var i;
var payload = { //<=== 293
"status" : (tweet.text || tweet)
};
Your code invokes this method with a single string parameter, status, which is set to "test".
The author of the library allowed for the tweet parameter to be one of two things:
It can be an object with a text property containing the message to Tweet, or
It can be a string.
However, the way that's being handled checks for tweet.text first, then if that does not exist it checks for a string tweet. When tweet.text does not exist (i.e. when using just a string), that TypeError is thrown.
I've reached out to the library author so they can publish the fix. However, in the meantime you can send a Tweet object with a text property, or take a copy of the library and update it yourself.
Send Tweet object. The Tweet object is documented in the Twitter API v1.1 documentation, but since the only property involved in this operation is text, a simple change in your status function will do the trick. Just ensure that status is an object with a text property.
function sendTweet(status) {
if (typeof status === string)
status = {text:status};
...
Update the library yourself.
To avoid the error, and handle the parameter options properly, line 294 in the library should be:
"status" : (tweet.hasOwnProperty("text") ? tweet.text : tweet)
Or:
"status" : (typeof tweet === 'object' ? tweet.text : tweet)
You'll need to publish it, and update the library ID in your code, but that should take care of this problem. Once a library update is available, you can switch back.

Couchbase Java API and javascript view not returning value for a specific Key

I am using couchbase API in java
View view = client.getView("dev_1", "view1");
Query query = new Query();
query.setIncludeDocs(true);
query.setKey(this.Key);
ViewResponse res=client.query(view, query);
for(ViewRow row: res)
{
// Print out some infos about the document
a=a+" "+row.getKey()+" : "+row.getValue()+"<br/>";
}
return a;
and the java script view in couchbase
function (doc,meta) {
emit(meta.id,doc);
}
So, when I remove the statement query.setkey(this.Key) it works returns me all the tables, what am I missing here .. How can I change the function to refect only the table name mentioned in the key
Change the map function like this:
function (doc,meta) {
emit(doc.table,null);
}
it is good practice not to emit the entire document like:
emit(doc.table, doc)
NB: This is surprisingly important:
i have tried using setKey("key") so many times from Java projects and setting the key using CouchBase Console 3.0.1's Filter Result dialog, but nothing get returned.
One day, i used setInclusiveEnd and it worked. i checked the setInclusiveEnd checkbox in CouchBase Console 3.0.1's Filter Result dialog and i got json output.
query.setKey("whatEverKey");
query.setInclusiveEnd(true);
i hope this will be helpful to others having the same issue. if anyone finds another way out, please feel free to add a comment about it.
i don't know why their documentation does not specify this.
EXTRA
If your json is derived from an entity class in a Java Project, make sure to include an if statement to test the json field for the entity class name to enclose you emit statement. This will avoid the key being emitted as null:
if(doc._class == "path.to.Entity") {
emit(doc.table, null);
}

Categories

Resources