Get database data from different url pages - what is the best technology? - node.js

I want to create a mobile app that call various urls and get for each url a different response based on SQL Server data.
I try to use Nodejs for this job but when I get the data, I cannot retrieve a single response for that page.
Someone suggested to use Socketweb.io instead of routers... what is the best option for your experience?
This is the code:
var express = require('express');
var app = express();
var dbResp;
const sql = require("msnodesqlv8");
var buf = '';
var router = express.Router();
const connectionString = <my connection string>;
router.get('/page1', function (req, res) {
var query = "SELECT query 1";
sql.query(connectionString, query, (err, rows) => {
try {
grows = rows;
for (i = 0; i < rows.length; i++) {
buf += "get the data...";
}
}
catch {
if (err) {
console.log(err);
}
}
});
res.send(buf);
});
router.get('/page2', function (req, res) {
var query = "SELECT query 2";
sql.query(connectionString, query, (err, rows) => {
try {
grows = rows;
for (i = 0; i < rows.length; i++) {
buf += "get the data...";
}
}
catch {
if (err) {
console.log(err);
}
}
});
res.send(buf);
});
app.use('/page1', router);
app.use('/page2', router);
app.listen(8080, function () {
console.log('Example app listening on port 8080!');
});

Related

How to I dynamically insert key and value in JSON in the response of NodeJs API

This is the Input I am providing
{
"cities" : [
"kolkata",
"mumbai",
"chennai"
]
}
and this is the response I am receiving.
{
"weather": [
{
"chennai": "30C"
},
{
"mumbai": "27C"
},
{
"kolkata": "26C"
}
]
}
I want a response somewhat like
{
"weather" : {
"kolkata" : "26C",
"mumbai": "27C",
"chennai": "30C"
}
}
My code is as follows.
const express = require('express');
const router = express.Router();
const bodyParser = require('body-parser');
const request = require('request');
const app = express();
const apiKey = 'c6068c4018def9330b01366aed03b08e';
app.use(express.static('public'));
app.use(bodyParser.json());
router.post('/getWeather', function (req, res) {
let cities = req.body.cities;
let weatherJson = [];
for(let i=0; i<cities.length; i++)
{
let city = cities[i];
let url = `http://api.weatherstack.com/current?access_key=${apiKey}&query=${city}`;
request(url, function (response, body) {
if (response) {
return res.json({ error: response });
}
let weather = JSON.parse(body.body);
if (weather.current == undefined) {
return res.json({ error: "somethin went wrong!" });
}
let weatherText = `${weather.current.temperature}C`;
weatherJson.push({ [city] : weatherText });
if(weatherJson.length == cities.length) {
console.log("here");
res.json({"weather": weatherJson});
}
});
}
});
app.use('/', router);
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
I have tried adding as hashmap, adding in array format then using stringify at the response point, but nothing seems to work. I just want to convert the format of the response to the desirable one with as minimalistic change in the code as possible. Please help.
You have a few issues, first off you're storing weatherJson (response) as an array when you say you want it to be a map.
here's how I would implement this:
router.post("/getWeather", async function (req, res) {
let cities = req.body.cities;
let weatherJson = {};
for (let i = 0; i < cities.length; i++) {
let city = cities[i];
let url = `http://api.weatherstack.com/current?access_key=${apiKey}&query=${city}`;
try {
const response = await fetch(url);
let weather = JSON.parse(response.body);
if (weather.current == undefined) {
return res.json({ error: "somethin went wrong!" });
}
let weatherText = `${weather.current.temperature}C`;
weatherJson[city] = weatherText;
} catch (err) {
return res.json({ error: err });
}
}
res.json({ weather: weatherJson });
});
You should use node-fetch instead of request which is obsolete. It does the same thing but much cleaner with promises instead of callbacks.
try creating an object instead of an array.
const express = require('express');
const router = express.Router();
const bodyParser = require('body-parser');
const request = require('request');
const app = express();
const apiKey = 'c6068c4018def9330b01366aed03b08e';
app.use(express.static('public'));
app.use(bodyParser.json());
router.post('/getWeather', function (req, res) {
let cities = req.body.cities;
let weatherJson = {};
for(let i=0; i<cities.length; i++)
{
let city = cities[i];
let url = `http://api.weatherstack.com/current?access_key=${apiKey}&query=${city}`;
request(url, function (response, body) {
if (response) {
return res.json({ error: response });
}
let weather = JSON.parse(body.body);
if (weather.current == undefined) {
return res.json({ error: "somethin went wrong!" });
}
let weatherText = `${weather.current.temperature}C`;
weatherJson[city]=weatherText;
if(Object.keys(weatherJson).length == cities.length) {
console.log("here");
res.json({"weather": weatherJson});
}
});
}
});
app.use('/', router);
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});

How to clean nodejs response after every user request?

Every time a user enter to our URL he get the response of the last user + his new response.
I'm new with nodejs and I think I don't understand the way this server works :)
Anyway, here you can see the app:
https://s1-nodejs.herokuapp.com (You will need to reload the page to see the duplicate response every time you reload).
And this is the code I deployed to Heroku:
const start = Date.now();
// using the http module
var http = require('http');
var https = require('https');
var request = require('request');
var domain;
var apiKey = 'example';
var domainResultJson = [];
var promises = [];
// look for PORT environment variable,
// else look for CLI argument,
// else use hard coded value for port 8080
port = process.env.PORT || process.argv[2] || 8080;
// create a simple server
let server = http.createServer(function (req, res) {
for (var i = 0 ; i < 10 ; i++ ) {
var domain = 'example-'+i+'.com';
promises.push(CheckIfDomainAvailable(https,domain,apiKey,domainResultJson));
}
Promise.all(promises).then(function(values) {
//console.log(values);
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
for (var i in values) {
val = values[i];
res.write(val);
}
res.end();
}).catch(
console.error
);
function CheckIfDomainAvailable(https,domain,apiKey,domainResultJson) {
return new Promise(function (success, failure) {
request('https://example.com/api/v1?'
+ 'apiKey=' + apiKey + '&d=' + domain + '', function (error, response, body) {
if (!error && response.statusCode == 200) {
domainResultJson.push('1');
success(body);
} else {
failure(error);
}
});
});
}
});
// listen on the port
server.listen(port, function () {
console.log('app up on port: ' + port);
});
Try to declare let promises = []; inside function (req, res) { ... }, like this:
// ...
let server = http.createServer(function (req, res) {
let promises = []; // <= Define promises container here.
for (var i = 0 ; i < 10 ; i++ ) {
var domain = 'example-'+i+'.com';
promises.push(CheckIfDomainAvailable(https,domain,apiKey,domainResultJson));
}
// ...

NODEJS, PUG, EXPRESS - Cannot read property 'length' of undefined

I have an API that i tweaked to make 2 calls to my DB and pull down information .. I can see the results in my console log so i know it is working
The next part is when it renders the view i need to show the results in two places
Here is the code for the API that makes 2 calls to the DB
function apples(req, res, next) {
sql.connect(config, function () {
var request = new sql.Request();
request.query("select price from table WHERE fruit = 'apples'", function(err, recordsetapples) {
var arrayLength = recordsetapples.length;
for (var i = 0; i < arrayLength; i++) {
console.log(recordsetapples[i]["price"]);
};
res.render('index', { resultsapples: recordsetapples });
return next();
});
});
};
function pear(req, res, next) {
sql.connect(config, function () {
var request = new sql.Request();
request.query("select price from table WHERE fruit = 'pear'", function(err, recordsetpear) {
var arrayLength = recordsetpear.length;
for (var i = 0; i < arrayLength; i++) {
console.log(recordsetpear[i]["price"]);
};
res.render('index', { resultspear: recordsetpear });
next();
});
});
};
app.get('/fruit', apples, pear);
So after that runs I can see the price print in console log .. Then i see this error
Cannot read property 'length' of undefined
What i expect to see if the price appear ... To get that info i have this code
tr
th.hidden-phone Fruit
th.hidden-phone Price
tr
each val in resultsapples
td.hidden-phone Apples
td.hidden-phone !{val.price}
tr
each val in resultspear
td.hidden-phone Pears
td.hidden-phone !{val.price}
The problem is your view expects both lists at the same time but you attempt to render the view twice with each list separately, which means in either scenario one list in the view will be undefined.
Even if you were to fix this, this approach won't work anyway because after the first res.render the HTTP response will end and return to the client. Ideally you would want to make one trip to the DB for both resultsets and then render the view e.g.
sql.connect(config, () => {
const request = new sql.Request();
request.query("select price from table WHERE fruit = 'apples' OR fruit = 'pear'", (err, result) => {
res.render('index', {
resultsapples: result.recordsets[0],
resultspear: result.recordsets[1]
});
});
});
As James mentioned your callbacks are async so you're trying to render the view twice. You also need some error handling in your sql functions
function apples(cb) {
sql.connect(config, function () {
var request = new sql.Request();
request.query("select price from table WHERE fruit = 'apples'", function(err, recordsetapples) {
if(err) {
return cb(err);
}
var arrayLength = recordsetapples.length;
for (var i = 0; i < arrayLength; i++) {
console.log(recordsetapples[i]["price"]);
};
cb(false, recordsetapples);
});
});
};
function pear(cb) {
sql.connect(config, function () {
var request = new sql.Request();
request.query("select price from table WHERE fruit = 'pear'", function(err, recordsetpear) {
if(err){
return cb(err)
}
var arrayLength = recordsetpear.length;
for (var i = 0; i < arrayLength; i++) {
console.log(recordsetpear[i]["price"]);
};
cb(false,recordsetpear);
});
});
};
app.get('/fruit', (req,res) => {
apples((appleerr,appleset) => {
if(appleerr){
//render error page
} else {
pear((pearerr, pearset) => {
if(pearerr) {
//render error page
} else {
return res.render('index', {
resultapples: appleset,
resultpears: pearset
});
}
})
}
});
});
Now for the record, I'm not a fan of nesting the callbacks like this so I would actually recommend you look at Promises and/or async/await but I'm not sure on your coding level so I didn't want to throw too many concepts at you at once.
Also whereas James has merged your SQL statements into one (which is probably the right approach for you) I kept them separate not knowing if you were reusing these individual pieces of code elsewhere and as such didn't want to combine them.
If you are interested in the promise implementation it might look as follows:
function apples() {
return new Promise((resolve,reject) => {
sql.connect(config, function () {
var request = new sql.Request();
request.query("select price from table WHERE fruit = 'apples'", function(err, recordsetapples) {
if(err) {
reject(err);
}
var arrayLength = recordsetapples.length;
for (var i = 0; i < arrayLength; i++) {
console.log(recordsetapples[i]["price"]);
};
resolve(recordsetapples);
});
});
};
function pear() {
return new Promise((resolve,reject) => {
sql.connect(config, function () {
var request = new sql.Request();
request.query("select price from table WHERE fruit = 'pear'", function(err, recordsetpear) {
if(err){
reject(err)
}
var arrayLength = recordsetpear.length;
for (var i = 0; i < arrayLength; i++) {
console.log(recordsetpear[i]["price"]);
};
resolve(recordsetpear);
});
});
});
};
app.get('/fruit', (req,res) => {
var applePromise = apples()
var pearsPromise = applePromise.then((appleSet)) {
return pear()
}
Promise.all([applePromise,pearsPromise]).then((([appleSet,pearSet]) => {
res.render('index', {
resultapples: appleSet,
resultpear: pearSet
});
}).catch((err) => {
//render error
})
});

Node js Printing info from JSON file using a function from another file V2.0

This is a continuation from another question I asked earlier Node.js Printing info from JSON file using a function from another JS file
In my previous question I had problems in calling a function from my data-service.js file that printed all the items in my JSON array, and had it resolved, but now I'm struggling in doing something similar in printing only the employees from my JSON array that I specify through the url. For example http://localhost:8080/employeesstatus=5 would print only the employee with a status of 5 however nothing is getting printed
SERVER.JS
var HTTP_PORT = process.env.PORT || 8080;
var express = require('express');
var data = require('./data-service');
var fs = require('fs');
var app = express();
var object = require('./data-service');
console.log("Express http server listening on 8080");
//app.get('/employees', function(req,res){
// return object.getAllEmployees()
// .then((response) => res.send(response))
//}); //QUESION FROM PREVIOUS POST WHICH WAS RESOLVED
app.get('/employees:?status=:value', function(req,res){
return object.getEmployeesByStatus(req.params.value)
.then((response) => res.send(response));
});
DATA SERVICE.JS
var employees = [];
var departments = [];
var error = 0;
var fs = require("fs");
function initialize(){
employees = fs.readFileSync("./data/employees.json", 'utf8', function(err, data){
if(err){
error = 1;
}
employees = JSON.parse(data);
});
departments = fs.readFileSync("./data/department.json", 'utf8',
function(err, data){
if(err){
error = 1;
}
departments = JSON.parse(data);
});
}
function check() {
return new Promise(function(resolve,reject){
if (error === 0){
resolve("Success");
}
else if(error === 1){
reject("unable to read file");
}
})
};
var getAllEmployees = function(){
return check().then(function(x){
console.log(x);
console.log(employees);
return employees;
}).catch(function(x){
console.log("No results returned");
});
}
var getEmployeesByStatus = function (status){
return check().then(function(x){
var employees2 = JSON.parse(employees);
for (var i = 0; i<employees2.length; i++){
if (employees2[i].status == status){
return console.log(employees2[i]);
}
}
}).catch(function(){
console.log("no results returned");
})
}
module.exports.getAllEmployees = getAllEmployees;
module.exports.getEmployeesByStatus = getEmployeesByStatus;
The 2 functions in question
app.get('/employees:?status=:value', function(req,res){
return object.getEmployeesByStatus(req.params.value)
.then((response) => res.send(response));
});
var getEmployeesByStatus = function (status){
return check().then(function(x){
var employees2 = JSON.parse(employees);
for (var i = 0; i<employees2.length; i++){
if (employees2[i].status == status){
return employees2[i];
}
}
}).catch(function(){
console.log("no results returned");
})
}
1) You should replace /employees route with the following
app.get('/employees/status=:value', function(req,res){
return object.getEmployeesByStatus(req.params.value)
.then((response) => res.send(response));
});
You are able to access using http://localhost:8080/employees/status=5
2) Return employees2[i] instead of console.log(employees2[i]).

Where should I do database queries and why am I not getting the results of the queries?

I'm new to node.js and the express framework.
Can anyone tell me if I'm doing this correctly?
I created a database.js as a module, and the code contains:
var mysql = require('mysql'),
dateFormat = require('dateformat'),
db = require('./dashboard');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'selenium',
timezone: '-07:00'
});
exports.selectalldate = function() {
connection.query('SELECT * FROM date', function (err, rows, fields) {
if (err) {
console.log(err);
}
if(rows.length > 0) {
for(i = 0; i < rows.length; i ++) {
rows[i].date = dateFormat(rows[i].date, "yyyy-mm-dd")
}
return rows;
} else {
return false;
}
});
}
I required it in my app.js, and when I call the selectalldate() to get all the dates from the database in app.js and see what's the results. I get undefined. What am I doing wrong here?
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, fs = require('fs')
, file = __dirname + '/test2'
, get = require('./routes/get')
, db = require('./routes/database')
;
app.get('/dashboard', function(req, res) {
var datee = db.selectalldate();
console.log(datee);
res.render('dashboard', {title: 'Selenium Dashboard', date: datee});
});
That's because the asynchronous nature of Node. Everything that has networking involved (DB queries, webservices, etc) is async.
Because of this, you should refactor your selectalldate() method to accept an callback. From that callback you'll be able to render your template successfully with the data fetched from the DB.
In the end, it'll be something like this:
exports.selectalldate = function(callback) {
connection.query('SELECT * FROM date', function (err, rows, fields) {
if(rows.length > 0) {
for(i = 0; i < rows.length; i ++) {
rows[i].date = dateFormat(rows[i].date, "yyyy-mm-dd")
}
}
callback(err, rows);
});
}
app.get('/dashboard', function(req, res) {
db.selectalldate(function(err, datee) {
if (err) {
// Handle the error in some way!
return;
}
res.render('dashboard', {title: 'Selenium Dashboard', date: datee});
});
});

Resources