Get JSON data from multiple files in a unique response - json

There are several files containing JSON data on my server. I want to receive the data contained in those files with a single GET request.
Right now my code looks like this:
app.get('/json', function(req, res){
fs.readFile(__dirname + '/file01.json', function(err, content){
var data01 = content;
});
fs.readFile(__dirname + '/file02.json', function(err, content){
var data02 = content;
});
res.send({file01: data01, file02: data02});
});
I know this is absolutely not the way to do it, the files are still being read when the response is sent, and i'm not sure if data01 and data02 are globally defined.
But then, what is the way to do it?
Should I use a stream? Should I use multiple res.write() instead? Enlighten me.

Perfect fit for async.parallel.
var async = require('async');
app.get('/json', function(req, res) {
var work = {
file01: async.apply(fs.readFile, __dirname + '/file01.json'),
file02: async.apply(fs.readFile, __dirname + '/file02.json')
};
async.parallel(work, function (error, results) {
if (error) {
res.status(500).send(error);
return;
}
//might need string->Object here
results['file01'] = JSON.parse(results['file01']);
results['file02'] = JSON.parse(results['file02']);
res.send(results);
});
});

Use the callback of each readFile to do the next operation:
fs.readFile(__dirname + '/file01.json', function(err, content){
var data01 = content;
//Might be smart to do some err checking here
//if (err) send error
//else read the next file
fs.readFile(__dirname + '/file02.json', function(err, content){
//if (err) again
var data02 = content;
res.send({file01: data01, file02: data02});
});
});

Related

Why does Node.js on http-server freeze when you enter url parameter

I'm setting up a node.js server, and want to fix problem with freezing loading using http-server lib.
I've tried doing other URL parameter methods but it doesn't work and doesn't show any errors on console.
var url = require('url');
http.createServer(function (req, res) {
var queryData = url.parse(req.url, true).query;
if (req.url == '/watch') {
if (!queryData.id) { res.write("Missing watch id?"); res.end(); }
res.end();
fs.readFile('player.html', function (err, html) {
if (err) {
throw err;
}
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(html + "<div id='b6'>" + queryData.id + "</div>");
res.end();
});
}
});
I expect the output to get URL parameter and show the player.html.
There may be more than one issue, but as-written, you have an errant res.end(), before you read in your player.html and return it to the response. Remove that line and see if it behaves as you expect.

show json data in index file

I dont understand why I cant display my json data. I am new to javascript and I want to display the data in the json file to my index file.
I have used the express generator for all the files. I did read that I should add this FS code in my app.js, but I cant use the data variable in my index file in my view. Any help ?
var express = require('express');
var router = express.Router();
var fs = require('fs');
/* GET home page. */
router.get('/', function(req, res, next) {
var file = __dirname + '/public/list/list.json';
var data;
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
data = JSON.parse(data);
console.log(data);
});
res.render('index', { title: data });
console.log(data);
});
module.exports = router;
here is my json file
{
"username":"xyz",
"password":"xyz#123",
"email":"xyz#xyz.com",
"uid": 1100
}
fs.readFile is asynchronous , so you should put res.render(..) inside his callback , because it will fired when the readFile function ends. So change your code to :
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
data = JSON.parse(data);
console.log(data);
res.render('index', { title: data });
});
The above answer is correct, but there's also an alternative.
If you're using this file for your index page, it'd be used a lot. If the data isn't changing, you can simply require the JSON file at the top of your code and return it in the request.
var express = require('express');
var router = express.Router();
var list = require(__dirname + '/public/list/list.json');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: list });
});
module.exports = router;
However, if that data does change frequently, reading the file is the way to go.

Serving HTML file from Node server

Pretty much purely for pedagogical purposes, I'm serving both my front and back end data out of my one node server. Right now, I'm at the point where I've received my client request successfully, created some data based on said request, am able to console log it, etc. Everything is fine up to that point. My issue is that in the event that my data is only an html file, which is being read with the fs library, it will not render on the page when I attempt to serve it out in my res.end() or res.write(). I can see it's exactly what I want and expect when I console log it, but it just doesn't render in the browser. Any help would be appreciated. I've got it set up to where I'm handling my requests in an "if/else" wherein I only have the two scenarios of "/" (home), in which case I serve the html file, and anything else because the server really only needs to handle those two events. Thanks in advance.
Edit. This is what I have so far:
function responseHandler(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
if (req.url.match("fav")) {
res.end("");
return;
}
else if (req.url.match("/endpoint")) {
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
res.end(data);
console.log(input, req.url)
}
else {
fs.readFile("index.html", "utf8", function(err, data) {
console.log("data:" + data);
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
});
}
res.end();
}
I can see the data in the console which, in the last case, is just my HTML file. It just won't render in the page.
How did you attempted to serve the html with res.end() and res.write() ?
I just made a small test here, and this works:
app.js
var http = require('http');
var fs = require('fs');
var html = fs.readFileSync('hello-world.html');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(html);
}).listen(8000);
hello-world.html
<h3>Hello World</h3>
Edit: To match with your code, try this:
function responseHandler(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
if (req.url.match("fav")) {
res.end("");
return;
} else if (req.url.match("/endpoint")) {
var input = req.url.match(/endpoint\/(.*)/)[1];
var output = endpoint.toHTML(decodeURI(input));
console.log(input, req.url);
// we have no data variable in this scope
res.end("");
// I added a return statement in each step
// Just to be clear that we don't want to go if any
// condition have fit, since we cannot call res.end()
// more than once
return;
} else {
fs.readFile("index.html", "utf8", function(err, data) {
// error handling
if (err) return res.end(err);
// now we have the data
console.log("data:" + data);
res.end(data);
});
return;
}
}
Serving html in asynchronous way works something like that;
var fs = require('fs');
var http = require('http');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile('index.html', function(err, data){
if(err){
return console.log(err);
}
res.end(data);
});
}).listen(8080);
console.log('Server is running on Port: 8080');

NodeJS: saving JSON to MongoDB

I am trying to get JSON from an API and store it into a MongoDB database.
Obviously, it doesn't work. My app seems to hang around the point where I try to save the data to the database. Please advise what to do.
Here's my code:
var express = require('express');
var router = express.Router();
var http = require('http');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/zak", {native_parser : true});
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
var site = 'http://www.vsechnyzakazky.cz/api/v1/zakazka/?format=json&limit=2';
function getData(cb) {
http.get(site, function(res) {
// explicitly treat incoming data as utf8 (avoids issues with multi-byte chars)
res.setEncoding('utf8');
// incrementally capture the incoming response body
var body = '';
res.on('data', function(d) {
body += d;
});
// do whatever we want with the response once it's done
res.on('end', function() {
try {
var parsed = JSON.parse(body);
} catch (err) {
console.error('Unable to parse response as JSON', err);
return cb(err);
}
// pass the relevant data back to the callback
cb(
parsed.objects
);
});
}).on('error', function(err) {
// handle errors with the request itself
console.error('Error with the request:', err.message);
cb(err);
});
}
function writeData (data, allGood){
// couple of visual checks if all looking good before writing to db
console.log('writing');
console.log(typeof data);
console.log(data);
db.collection('zakazky').save(data, function(error, record){
if (error) throw error;
console.log("data saved");
});
}
function allGood(){console.log('all done');}
getData(writeData);
// ---------------------
module.exports = router;
You are calling the save() instead of insert(). Change this part and it will work:
// this should call insert, not save
db.collection('zakazky').insert(data, function(error, record){
if (error) throw error;
console.log("data saved");
});

how to import function value from var require?

I have this code:
server.js:
var sql = require('./libs/mysql');
app.get('/status', function(req, res) {
res.send(sql.readName('1600'));
});
mysql.js:
exports.readName = function(name){
var connection = mysql.createConnection(option);
connection.connect();
connection.query('SELECT id FROM asterisk.users WHERE name= '+name, function (err, rows, fields) {
console.log('mysql: ' +rows[0].id);
return(rows[0].id);
});
Now, when I send GET http://mydomain.com/status I can not receive responce. But in console log I see correct answer. Where is my error?
Most disk reading/DB access in node.js is done asynchronously. This allows node.js to be as fast as it claims. You need to use callback functions to handle the result of these read operations. If you are familiar with ajax, the concept is similar.
You are returning from connection.query which runs asynchronously. This is returned nowhere. readName actually returns nothing. What you need to do is actually pass in the callback that returns the value:
app.get("/status", function (req, res) {
sql.readName("1600", function (err, rows, fields) {
/* handle err */
res.send(rows[0].id);
});
});
This callback has to be called of course:
exports.readName = function (name, cb) {
/* snip */
connection.query(query + name, cb);
});
You can't get the result because the return statement is in the function function (err, rows, fields). You can use callback like this
var sql = require('./libs/mysql');
app.get('/status', function(req, res) {
sql.readName('1600', function(result){
res.send(result);
});
});
exports.readName = function(name, callback){
var connection = mysql.createConnection(option);
connection.connect();
connection.query('SELECT id FROM asterisk.users WHERE name= '+name,
function (err, rows, fields) {
console.log('mysql: ' +rows[0].id);
callback(rows[0].id);
});
}
Thanks for helping. I find http error causes described upper. Error appear if I use callback functions like this callback(row[0].id), but if we use syntax like this callback('id: '+row[0].id) everything it's ok. So when we send res.send(response) we cant send unnamed data, need to put there some descriptions.
So, my final code look like this:
server.js
var sql = require(./mysql);
app.get('/status', function(req, res) {
sql.readName('1600', function(result){
res.send(result);
});
});
mysql.js
var mysql=require(mysql);
exports.readName = function(name, callback){
var connection = mysql.createConnection(option);
connection.connect();
connection.query('SELECT id FROM asterisk.users WHERE name= '+name,
function (err, rows, fields) {
if(err) callback(err);
else{
console.log(rows[0].id);
callback('ID: '+rows[0].id);
}
});
return true;
};