How take the JSON in Node.JS - javascript

I have this in Node.JS file.
var express = require('express');
var app = express();
var http = require('http').Server(app);
var cfenv = require("cfenv");
var appEnv = cfenv.getAppEnv();
http.listen(appEnv.port, appEnv.bind);
var PersonalityInsightsV2 = require('watson-developer-cloud/personality-insights/v2');
var personality_insights = new PersonalityInsightsV2({
username: '<YOUR-USERNAME>',
password: '<YOUR-PASSWORD>'
});
personality_insights.profile({
text: "<YOUR-100-UNIQUE-WORDS>",
language: 'en' },
function (err, response) {
if (err)
console.log('error:', err);
else
console.log(JSON.stringify(response, null, 2));
});
I am sending an API call but as you can see, it shows me the result in JSON in the console.
How can I make this result in JSON that shows me in the console, show it to me in an HTML?
Thank you very much!
I supose that the problem is in console.log(JSON.stringify(res,null, 2));, but, I don't know how put this in HTML.

You can't just turn JSON into HTML. JSON is a data format. HTML is a markup language. You'll manually have to create some HTML with the way you want it, and then drop in values from the JSON.
For example, you could do something like this:
else {
const html =
`<!DOCTYPE html>
<body>
<p>${response.name}</p>
`;
console.log(html);
}
That would give you some HTML like:
<!DOCTYPE html>
<body>
<p>Bob</p>
assuming response has a value of name.

It sounds like you're wanting to view the JSON on an HTML page in a browser. Something like this should help. It will start your Express server listening on whatever port you specified using appEnv.port, and will serve up myJson (which will then be assigned in your code)
var express = require('express');
var app = express();
var http = require('http').Server(app);
var cfenv = require("cfenv");
var appEnv = cfenv.getAppEnv();
var myJson;
// respond with JSON when a GET request is made to the index
app.get('/', function (req, res) {
res.send(myJson)
})
app.listen(appEnv.port);
var PersonalityInsightsV2 = require('watson-developer-cloud/personality-insights/v2');
var personality_insights = new PersonalityInsightsV2({
username: '<YOUR-USERNAME>',
password: '<YOUR-PASSWORD>'
});
personality_insights.profile({
text: "<YOUR-100-UNIQUE-WORDS>",
language: 'en' },
function (err, response) {
if (err)
console.log('error:', err);
else
myJson = JSON.stringify(response, null, 2);
});
To try this, you would open your browser to "http://localhost:appEnv.port/" (where appEnv.port is the port you chose). You should see your JSON output

Related

How to pass parameters between node.js and HTML?

I am a new user of node.js and mongodb and still learning. Please excuse if the question seems very simple. My node.js MongoDB query script (hello.js) is-
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var url = 'mongodb://localhost:27017/flood';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server.");
var collec_name="99"
var field_name ="data1"
var value=311
db.collection(collec_name).find({data0:value}, {[field_name]:1, _id:0}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
The query runs fine with command- node hello.js and got the expected value result (for instance, output value of result is 0.000115). Note that var collec_name="99", var field_name ="data1" and var value=311 contain fixed values.
My HTML file (index.html) is-
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var c_n = "99";
var f = "data1";
var v = 311;
document.getElementById("demo").innerHTML = 0.000115;
</script>
</body>
</html>
Now, I want to pass the values of variable c_n, v and f from index.html to hello.js by replacing three statements of hello.js as-
var collec_name=c_n
var field_name = f
var value = v
Then, I want to pass value of result from hello.js to the index.html by replacing one statement of index.html as-
document.getElementById("demo").innerHTML = result;
So, how can I achieve these parameter passing so that if I run the index.html page, I can display the value of result on the web? Any solution script based on my scripts will be highly appreciated.
To send data between your back-end and your client you have to use AJAX, socket.io or WebSockets.
If you only have to update the back-end if the clients wants to you should use AJAX. If your client has to be notified by the back-end (Server), you should use socket.io or WebSockets for that.
Because you are using NodeJs, i would recommend you to use socket.io.
Just have a look at it:
https://socket.io/
Here a example for your code:
First install the package:
npm install -S socket.io
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
// add socket io
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
// connect to port
app.listen(3030);
var url = 'mongodb://localhost:27017/flood';
// setup server
io.on('connection', function (socket) {
// add event
socket.on('data', function (data) {
// execute after event was emitted
MongoClient.connect(url, function (err, db) {
assert.equal(null, err);
console.log("Connected correctly to server.");
var collec_name = data.collec;
var field_name = data.field;
var value = data.value
db.collection(collec_name).find({ data0: value }, { [field_name]: 1, _id: 0 }).toArray(function (err, result) {
if (err) throw err;
// TODO add emmit
console.log(result);
db.close();
});
});
});
});
HTML:
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script src="path/to/socket.io"></script>
<script>
var socket = io('http://localhost');
// send message
socket.emit('data', {
collec: "99",
field: "datal",
value: 311
});
// TODO add listener
document.getElementById("demo").innerHTML = 0.000115;
</script>
</body>
</html>
Finally, I was able to solve the problem. As I didn't find any perfect solution on net, I thought it will be helpful for other users (who are facing similar problem) if I post a general solution to a similar problem here. Please excuse if this is not the right place to post the solution.
My Solution: This is not the exact solution of my above example but I think it is better to provide a general solution to a similar problem so that anyone can always modify/update this solution according to his/her example/need as basic approach will be always same. At first, you need to have http, express and body-parser and you can do by following the commands:
npm install http
npm install express
npm install body-parser --save
A general problem: Suppose, I have two numbers (for instance a = 20 and b = 24 in the client HTML page and I want to sum up the numbers from the server side and get the summation result (sum = 44) back in the client side to display in the HTML page. Then use the following nodejs and ejs scripts-
index.ejs:
<html>
<head>
<title>Example solution</title>
<script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
<script type="text/javascript">
$(function(){
$('#loadRequest').click(function(e) {
e.preventDefault();
console.log('Load_button clicked');
var data = {};
data.a = 20; //input
data.b = 24; //input
$.ajax({
type: 'POST',
data: JSON.stringify(data), //input data to be sent to the server
contentType: 'application/json',
url: 'http://localhost:80/endpoint',
success: function(res) {
console.log('success');
console.log(res);
$("#demo").html(res); //summation displayed in the HTML page
}
});
});
});
</script>
</head>
<body>
<p id ="demo"></p>
<button id="loadRequest">Load</button>
</body>
</html>
server.js:
var http = require('http');
var express = require('express');
var app = express();
app.set('view engine', 'ejs'); //tell Express we're using EJS
app.set('views', __dirname + '/views'); //set path to *.ejs files
app.use('/public', express.static(__dirname + '/public'));
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.get('/', function(req, res) {
//render index.ejs file
res.render('index');
});
app.post('/endpoint', function(req, res){
var x = req.body.a; //received input 1 from client side
var y = req.body.b; //received input 2 from client side
console.log(x);
console.log(y);
var sum =x+y;
console.log(sum);
res.send(String(sum)); //sending summation to the client
});
http.createServer(app).listen(80);
It worked perfectly. Please let me know if you have any comment/feedback.
You can either implement an API yourself using AJAX, WebSockets or socket.io - or you can go ahead and take a look into Express framework.
Setting up a Node.js server using Express will not only provide you access to a rich API interface, it would also make your task much easier.
Using it, you can set up a simple route like this:
app.post('/compute', function(req, res){
// compute 'result'
res.send(result);
});

Issue when doing web scraper

I am scraping the webpage https://www.g2a.com/rising-storm-2-vietnam-steam-cd-key-global.html
I need to get the title from the table data.
var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var app = express();
app.get('/scrape', function(req, res) {
url = 'https://www.g2a.com/rising-storm-2-vietnam-steam-cd-key-global.html';
request(url, function(error, response, body) {
if (!error) {
var $ = cheerio.load(body);
var arr = [];
var title = $('.mp-user-rating tr').each(function() {
var tableData = $('.marketplace-name > .mp-rating-popup');
arr.push({ 'title': tableData.text() });
});
}
res.send('Check your console!')
});
})
app.listen('8081');
console.log('Magic happens on port 8081');
exports = module.exports = app;
Here the data is in third column and cannot able to get .mp-user-rating tr data what is expected.
The image shows the structure of the table
Any help would be appreciated.
So, I went to the page and ran this in the console.
var arr = [];
var title = jQuery('.mp-user-rating tr').each(function(i, element) {
var tableData = jQuery(element).find('.mp-rating-popup');
arr.push({ 'title': tableData.text() });
});
console.log(arr);
The array consists of 8 objects that each have the titles within them.
UPDATE:
I pulled in the html information using your code. I think the issue is, the html is loaded asynchronously by the website, as a result, pulling the html will only retrieve the static markup. You will need to use PhantomJS or chrome's headless browser in order to load the website and allow the asyncronous information to load, then you can grab the html.
See here for some good docs on PhantomJS: https://github.com/Medium/phantomjs

nodejs sends empty response before data retrieved from mongodb

When I use jQuery ajax to retrieve data from nodejs (with express4), nodejs sends empty response back before data loaded from mongodb.
This is the message from nodejs console:
GET /query?uid=1 - - ms - -
And this is the error message from Chrome console:
GET http://192.168.1.105:3000/query?uid=1 net::ERR_EMPTY_RESPONSE
I can confirm that data are correctly loaded from mongodb because data can be printed on nodejs console after nodejs sent the empty response. And this is exactly the problem. Why nodejs sends reponse to client before data have been prepared?
I know nodejs is asynchronous and I pay much attention to this great feature, but I still have this problem.
This is my client code:
$.getJSON('/query', {uid:1}, function(response) { console.log('finished!'); });
And this is my server code:
var express = require('express');
var mongodb = require('mongodb');
var GeoJSON = require('geojson');
var strftime = require('strftime');
var router = express.Router();
var MongoClient = mongodb.MongoClient;
router.get('/query', function(req, res, next) {
var url = "mongodb://localhost/example_db";
var collection_name = "example_collection";
var poi = req.query.poi ? req.query.poi.split("||") : null;
var time = req.query.time;
var uid = req.query.uid;
var condition = {};
if (poi) condition.poiname = {$in: poi};
if (time) condition.checkin_time = {$gte:new Date(time.start_time), $lte:new Date(time.end_time)};
if (uid) condition.uid = parseInt(uid);
MongoClient.connect(url, function(err, db) {
if (err) console.log('connection error');
var collection = db.collection(collection_name);
collection.find(condition).sort({checkin_time:1}).toArray(function(err, result) {
if (err) {
console.log(err);
return res.send('error!');
}
if (!result) return res.send('no data');
//This line prints the result after empty response has been sent.
console.log(result);
var data = {};
data['geojson'] = GeoJSON.parse(result, {Point:'loc', include:['poiname', 'uid', 'checkin_time']});
res.json(data);
db.close();
});
});
My data are a little bit large, 12G stored in mongodb. So it usually takes about 3 minutes or more to complete the query. When I use findOne to retrieve only a single document, this is no problem.
Does the data size cause the problem?
Try GeoJSON.parse with callback
var data = {};
GeoJSON.parse(result, {Point:'loc', include:['poiname', 'uid', 'checkin_time']}, function (geojson) {
data['geojson'] = geojson;
res.json(data);
db.close();
});

Using Node.js to retrieve data from Redis through an AJAX request

I'm going through a Node, Express, & Socket.io chat tutorial. I decided to use Redis to store the chat history and have successfully set it up so that my information is correctly posting to the database. I am now trying to access that information to use on the client-side (in this case I'm trying to access the list of users currently in the chat so I can show them to the side of the chat). I am using $.getJSON to make a GET request. Right now I have it setup so that the file it tries to access only has this JSON object : {"dog" : "2","cat":"3"} just to test it, and that is working, but I'm not sure where to go from there because anytime I try adding a function into that file, even if I specify to return a JSON object and call that function, the request stops returning the correct information.
For example I tried :
var data = function(){
return {"dog" : "2","cat":"3"}
}
data();
and that doesn't return anything ( I understand that when I make a GET request the function isn't run, but it doesn't even return that text, and if it doesn't run a function than I'm not sure how I can access redis from this file)
Here's what I'm thinking:
var redis = require('redis')
//figure out how to access the redis client that I have at localhost:6379, something like var db = redis.X
//and then call (for example) db.smembers('onlineUsers') and be returned the object which I can iterate through
Here's my relevant code:
server.js:
var jade = require('jade');
var PORT = 8080;
var redis = require('redis');
var db = redis.createClient();
var pub = redis.createClient();
var sub = redis.createClient();
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(PORT, function(){
console.log("Now connected on localhost:" + PORT)
});
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set("view options", {layout: false});
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
res.render('home');
});
io.sockets.on('connection', function(client){
sub.subscribe("chatting");
sub.on("message", function (channel, message) {
console.log("message received on server from publish");
client.send(message);
});
client.on("sendMessage", function(msg) {
pub.publish("chatting",msg);
});
client.on("setUsername", function(user){
pub.publish("chatting","A new user in connected:" + user);
db.sadd("onlineUsers",user);
}
);
client.on('disconnect', function () {
sub.quit();
pub.publish("chatting","User is disconnected :" + client.id);
});
});
script.js:
$(document).ready( function(){
$client = io.connect();
initialize();
});
var setUsername = function(){
var username = $("#usernameInput").val();
if (username)
{
var user = username;
$client.emit('setUsername', username);
$('#chatControls').show();
$('#usernameInput').hide();
$('#usernameSet').hide();
showCurrentUsers();
}
}
var showCurrentUsers = function(){
$('#list_of_users').empty();
$.getJSON('getusers.js', function(data){
for (var i = 0; i < data.length; i++){
$('list_of_users').append("<li>"+data[i]+"</li>")
}
})
}
var sendMessage = function(){
var msg = $('#messageInput').val();
var username = $("#usernameInput").val();
if (msg)
{
var data = {msg: msg, user: username}
$client.emit('message', data);
addMessage(data);
$('#messageInput').val('');
// populate(username,msg);
}
}
var addMessage = function(data) {
$("#chatEntries").append('<div class="message"><p>' + data.user + ' : ' + data.msg + '</p></div>');
}
// var populate = function(username,msg) {
// var data ;
// }
var initialize = function(){
$("#chatControls").hide();
$("#usernameSet").on('click', setUsername);
$("#submit").on('click',sendMessage);
showCurrentUsers();
}
and right now all that the getusers.js file has in it is:
{"dog" : "2","cat":"3"}
It looks like you're expecting your call to $.getJSON to load and execute the javascript it loads. It doesn't work this way. You need to make a node endpoint (via a route) which renders the JSON. The node endpoint would then do the data manipulation / querying redis:
Node:
In routes.js:
app.get('/chatdata', ChatController.getChatData);
In ChatController.js (manipulate, create the data as you like here)
exports.getChatData = function (req, res) {
var data = function(){
return {"dog" : "2","cat":"3"}
};
res.JSON(data);
};
Front-end
$.getJSON('getChatData', function(data){
//...
})
I think you need to setup a route to handle the GET request that $.getJSON makes, or if getusers.js is in the /public directory, then you need to modify your $.getJSON call as follows:
$.getJSON('http://localhost:8080/public/getusers.js', function(data){
Ok, it looks like it is a problem with your getusers.js file. $.getJSON seems to prefer double quotes. Try formatting it like this:
{
"dog" : "2",
"cat" : "3"
}
Also, try using this to display the data:
$.getJSON('getusers.js', function(data){
var items = [];
$.each( data, function( key, val ) {
items.push("<li id='" + key + "'>" + val +"</li>");
});
$('#list_of_users').append(items.join(""));
});

Auto-adding pages with node.js on heroku?

It would be wonderful if you could help me with this!
I'm using node.js and heroku to deply an app and I'm changing my web.js file everything I add a new post. This was fine earlier, but with more pages, it's starting to get out of hand. I'm wondering if I could automate this?
Eg, this is what my web.js file looks like now:
var express = require('express');
var fs = require('fs');
var htmlfile = "index.html";
var app = express(express.logger());
//day 7 and so on.. till day 15.
var day6 = "./100/day6/day6.html";
app.get('/day6', function(request, response) {
var html = fs.readFileSync(day6).toString();
response.send(html);
});
var day5 = "./100/day5/day5.html";
app.get('/day5', function(request, response) {
var html = fs.readFileSync(day5).toString();
response.send(html);
});
var day4 = "./100/day4/day4.html";
app.get('/day4', function(request, response) {
var html = fs.readFileSync(day4).toString();
response.send(html);
});
var day3 = "./100/day3/day3.html";
app.get('/day3', function(request, response) {
var html = fs.readFileSync(day3).toString();
response.send(html);
});
var day2 = "./100/day2/day2.html";
app.get('/day2', function(request, response) {
var html = fs.readFileSync(day2).toString();
response.send(html);
});
var challengehtmlfile = "100.html";
app.get('/100-day-challenge', function(request, response) {
var html = fs.readFileSync(challengehtmlfile).toString();
response.send(html);
});
var bloghtmlfile = "blog.html";
app.get('/blog', function(request, response) {
var html = fs.readFileSync(bloghtmlfile).toString();
response.send(html);
});
app.get('/', function(request, response) {
var html = fs.readFileSync(htmlfile).toString();
response.send(html);
});
var port = process.env.PORT || 8080;
app.listen(port, function() {
console.log("Listening on " + port);
});
If you are planning to add much more pages, it is not a good idea to add one route per page. Better way is to use pattern matching in your routing. For example,
app.get('/day/:num', function(request, response) {
var day = "./100/day" + request.params.num + "/day" + request.params.num + ".html";
var html = fs.readFileSync(day).toString();
response.send(html);
});
Now this route would match any number of days. Only thing you would have to change is the URL. Instead of '/day3', you should access '/day/3'.
In /day/:num, :num is just a variable name in the url. You access that variable through request.params.num. Then you construct the filename with that information. Hope this would clean up your script. :)
For more info, check express api here (http://expressjs.com/api.html#req.params).
Copy this code and save it as "insert.sh".
#!/bin/bash
count=$1
day=day$1
sed -i "/express(express.logger());/avar ${day} = \"./100/${day}/${day}.html\";\napp.get('/${day}', function(request, response) {\nvar html = fs.readFileSync(${day}).toString();\nresponse.send(html);\n});\n" $2
This script takes two parameters: # of days and file name. For example,
bash insert.sh 3 yournode.js
This command will insert the necessary code for day3 in your node.js file. I assumed you want to add those lines after express.logger() line. If you want to put the code after a different line, simply replace express(express.logger()); in the script to anything you want. Please let me know.

Categories

Resources