JSON value gives undefined - javascript

I have created an electron app that fetches a JSON value from https://complimentr.com/api. But, when you click the button to set the innerHTML value to the JSON value, it gives the dreaded 'undefined'.
// create a variable called url and set it to the url of the website
var url = "https://evilinsult.com/generate_insult.php?lang=en&type=json";
// create a variable called response and set it to the response of the get request
request(url, function(error, response, body){
var data = JSON.parse(body);
console.log(data.compliment);
const btn = document.getElementById('button-1');
btn.onclick = () => {
document.body.innerHTML = data.compliment
}
});
Is there any reason this isn't working? I am new at JavaScript so this could be an easy fix.

It should be response.compliment not data.compliment
console.log(response.compliment);

Related

Javascript fetch getting undefined URL on window.popstate

I'm trying to fetch content from a php page. I have a fetch call + a history.pushState firing on click, which are both working fine, but window.popstate is returning an error when going back by pressing the browser's back button. The error is, that window.popstate doesn't know what url to fetch when going back.
Unfortunately I can't figure out how to pass the right url variable to window.popstate.
// the code stripped fetch function
var load = function(url){
fetch(url, {
method: "GET"
}).then(function(response) {
response.text().then(function(text) {
// parsing and temporary placing fetched content into a fragment
var content = new DOMParser().parseFromString(text, "text/html"),
bodyPart = content.querySelector('main'),
fragmentElement = document.createDocumentFragment(),
tempElement = fragmentElement.appendChild(bodyPart);
// replacing the current content with the fragment
document.body.replaceChild(tempElement, document.querySelector('main'));
// need to assign the fetch on click function again, otherwise it won't work on the dynamically added (the fetched) links
clickOnPJAXLink();
});
});
}
// the click function if clicking on any link function to start fetching content
var clickOnPJAXLink = function(url) {
document.querySelectorAll('A').forEach(a => {
a.addEventListener('click', (e) => {
e.preventDefault();
var url = e.currentTarget.getAttribute("href");
load(url);
history.pushState(url, "sometitle", url);
});
});
}
// load the function initially on the home page
clickOnPJAXLink();
// popstate for back button
window.addEventListener('popstate', function (e) {
var state = e.state;
if (state !== null) {
load(url);
console.log(url)
}
});
The window.popstate returns the error, that var url is undefined and thus of course cannot fetch the before (the history back) content.
Many thanks for any tips!
history.pushState takes a data object as the first parameter, not a string- try history.pushState({url:e.currentTarget.getAttribute("href")} then e.state.url will equal the url you want to load.

How to parse large nested json objects?

PasteBin JSON
I would like to get this as Object it says jsonlint is valid but parsing is not anyone help would appreciate
"Data":[{...},{...},] // structure build like this
when i try
JSON.parse(jsonparamter) <-- Uncaught SyntaxError: Unexpected token A in JSON at position 71
at JSON.parse (<anonymous>)
at <anonymous>:1:6
There are multiple levels of JSON encoded data so you will have to create a loop to decode the elements deeper in the JSON nest. Use the below code to see an example of accessing Data.Adress.Value in this dictionary
// set up urls and headers for making HTTP req
corsurl = 'https://cors-anywhere.herokuapp.com/'
jsonurl = 'https://pastebin.com/raw/vuecweML'
headerNames = ['Content-Type','Accept']
headerValues = [ 'application/json', 'application/json']
// Modular get request function that I use
function getRequest (baseRestURL, APIPath, headerNames, headerValues, callback) {
var completeRestURL = baseRestURL + APIPath
console.log('REST API URL: ' + completeRestURL)
var method = 'GET'
var url = completeRestURL
var async = true
var request2 = new XMLHttpRequest()
request2.onload = function () {
console.log('ONLOAD')
var status = request2.status // HTTP response status, e.g., 200 for "200 OK"
console.log(status)
console.log(request2.responseText)
var response = request2.responseText
return callback(response)
}
request2.open(method, url, async)
for (var i in headerNames) {
request2.setRequestHeader(headerNames[i], headerValues[i])
}
request2.send(null)
}
// Our code of interest
getRequest(corsurl, jsonurl, headerNames, headerValues, response => {
parsed = JSON.parse(response).Data //parse our data the first time, and get the data attribute from dictionary
objects = JSON.parse(parsed) // parse a second time ( as data is JSON encoded twice )
selection = JSON.parse(objects[0].Address)[0].Value // parse a third time and select an attribute
document.getElementById('result').innerHTML = selection // Add it to our html to display
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<div id='result'> Loading </div>

Sending data from NodeJS to the client by using Ajax calls

I increase a value at the server by running an Ajax call and want to update my UI after doing this
function increaseHitpoints(){
$.ajax({
type: 'GET',
url: 'http://localhost:8888/incHp/2312'
}).done(function (data) {
$("#txtHitpoints").html(data);
});
}
In my app.js I read a JSON file, manipulate the value, write it back to the file and return it to the client
app.get('/incHp/:id', function (req, res) {
var database = './database.json';
fs.readFile(database, 'utf8', function (err, data) { // read the data
var json = JSON.parse(data);
var users = json.users;
var hitpoints;
users.find(u => {
if (u.id === Number(req.params.id)) { // get the user by id
u.hitpoints++;
hitpoints = u.hitpoints;
}
});
json = JSON.stringify(json);
fs.writeFile(database, json, (err) => { // update the JSON file
// -> missing part here <-
});
});
});
what do I have to pass into the missing part if I want to return the new value? The new value would be hitpoints
I tried res.send(hitpoints); but it seems this function wants to return a status code, not a value.
If you send a numerical value, it will be observed as an HTTP response code
https://expressjs.com/en/api.html#res
But you can send your hitpoints as a string res.send(hitpoints.toString())or as json res.send({hits: hitpoints});
Depends on what format you want your response to be. I prefer using JSON. So in JSON case you would do this:
fs.writeFile(database, json, (err) => {
res.status(200).json({yourKey: yourValue});
});
Then you can access the JSON object in your frontend:
$("#txtHitpoints").html(data.yourKey);

Uncaught TypeError: Cannot read property 'total' of undefined

I get a JSON from my response object so I do:
var json = JSON.parse(res.text);
I print the JSON and get JSON back. But when I retrieve the value inside json.body.value.total then it gives this error:
Uncaught TypeError: Cannot read property 'total' of undefined
I have no idea why. I pasted the value that receive from var json and printed on console and was able to retrieve total. But I cannot do it through the code. There is a JSON value total. Its just unable to recognize. On the console, it works but does not work in the code.
I get JSON back from my response object which I retrieve using response.text. I think it needs to change in parsable object but all it returns is undefined
it('returns http 200', function (done) {
chai
.request(baseUrl)
.get('/api/')
.set('Authorization', 'Basic abc')
.query({val:'hey'})
.end(function(err, res) {
expect(res).to.have.status(200);
var json = res.text;
console.log('val: '+ JSON.parse(json.body));
var val = json.body.value.total; //undefined
expect(val.to.be.above(0)); //fails
done();
});
});
The REST API that I built was returning the response.body but what worked is this:
var body = JSON.parse(json.body);
var obj = JSON.stringify(body);
var jsonObj = JSON.parse(obj);
The above looks ridiculous but thats what worked. json -> object -> json. It was finding trouble to figure out that its a json object.
The console was doing a good job but not the library that I was using.
The complete code is this:
it('returns http 200', function (done) {
chai
.request(baseUrl)
.get('/api/')
.set('Authorization', 'Basic abc')
.query({val:'hey'})
.end(function(err, res) {
expect(res).to.have.status(200);
var json = res.text;
var body = JSON.parse(json.body);
var obj = JSON.stringify(body);
var jsonObj = JSON.parse(obj);
var val = jsonObj.body.value.total;
expect(val.to.be.above(0));
done();
});
});
You're not assigning the parsed value to json.
var json = res.text;
should be
var json = JSON.parse(res.text);
You have to put you json string into JSON.Parse() and access the properties on the result of the Parse function.
You can't just access properties from a text.

Node Express pass variable from client to server

I am trying to return value from an input box to a variable in route, by taking this source as a reference but am stuck, in the example author is searching a keyword, constructing a url using this keyword, and returning a body response.
My use case is a little different I need user to provide a url as a string in search box, which I would then pass to my request function to spit response body
Current app.js (server-side)
app.get('/searching', function(req, res){
// input value from search
var url = req.query.search;
console.log(url); // prints value
request({ uri: url}, function (error, response, body) {
if (!error) {
content = body;
console.log(content);
} else {
console.log('Oops! Error when contacting slack.com');
}
});
res.send(content);
});
main.js (client-side)
$(function(){
$('#submit').on( 'click', function () {
var sSearch = $('#search').val();
var parameters = { search: sSearch };
$.get( '/searching',parameters, function(data) {
$('#results').html(data);
});
});
});
I realize /searching in both above files must be replaced because currently its trying to 'search' the user entered url value as a query string, so if I enter "https://google.com" in the text box the application tries to search:
http://localhost:3000/searching?search=https%3A%2F%2Fgoogle.com
instead I need it to pass this url as is to the request function so that I can print the body response, which in this case would be the page's source code. But am not sure how should I proceed
index.jade (template)
extends layout
block content
input#search(type="search", placeholder="Enter Keyword")
button#submit(type='submit',class='btn btn-success') Search
h2#results
script(src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js")
script(src="/javascripts/main.js")
How should I format so that I can pass the variable from client to server and then send it back to client after processing? Any help is appreciated.
In the app.js you are making a async http call, but the response is sent before the http callback is invoked. Just move the res.send(content); inside the call back
app.get('/searching', function(req, res){
// input value from search
var url = req.query.search;
console.log(url); // prints value
request({ uri: url}, function (error, response, body) {
if (!error) {
content = body;
console.log(content);
} else {
console.log('Oops! Error when contacting slack.com');
}
res.send(content);
});
});
i see ajax request in your client code , so in your server code, try to response something like this :
res.status(200).json(content)
in your client code ,check if the content is there (console.log(data) before $().html(data)... )
PD : request is async , so you have to response inside request callback.

Categories