Node.js/Express Async functions - javascript

I'm playing with node.js and express. I have a little server which fetch sqlite contents and send everything to a Jade template. It works fine using this code :
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var async = require('async');
var result_title = [];
var result_scope = [];
var result_benefits = [];
var result_technical = [];
app.use(express.static(__dirname + '/views'));
app.get('/product1', function(req, res){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('products.db');
var check;
db.serialize(function() {
db.each("SELECT title, scope, body, technical_information FROM products", function(err, row) {
result_title.push(row.title);
result_scope.push(row.scope);
result_benefits.push(row.body);
result_technical.push(row.technical_information);
});
});
console.log(result_title[0]);
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
db.close();
});
app.listen(8080);
My issue is that when I go to page http://localhost/product1:8080 nothing is displayed. A manual refresh of the page is needed to load the content! My research tells me that I need to use Async functions. I edited my code :
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var async = require('async');
var result_title = [];
var result_scope = [];
var result_benefits = [];
var result_technical = [];
app.use(express.static(__dirname + '/views'));
app.get('/product1', function(req, res){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('products.db');
var check;
async.series([
function(callback) {
db.serialize(function() {
db.each("SELECT title, scope, body, technical_information FROM products", function(err, row) {
result_title.push(row.title);
result_scope.push(row.scope);
result_benefits.push(row.body);
result_technical.push(row.technical_information);
});
});
},
function(callback) {
// console.log(result_title[0]);
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
db.close();
}
], function(error, results) {
console.log('');
})
});
app.listen(8030);
But the webpage is loading, loading and nothing happens..
I made something wrong, but no idea where for the moment. If someone have an idea it could be great ;-) Thanks!

Your url is wrong also the second code block your port is different.
Give port name after domain or ip address , if not the request will go /product1:8080 and you haven't any router like that , so request goes to error page also it semes you haven't any error handling for 404.
Try : http://localhost:8080/product1 or http://localhost:8030/product1
Also you have an issue in your second code block :
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
This line should be executed in all series callback, If not you will not get data you want. Because it's still in async function.
], function(error, results) {
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
})
I have just investigated sqllite3 , you don't need to use async library as an extra in this situation(BTW in async functins you have to call callback with return parameter on it). In sqllite3 documentation db.each.
That latest code should work. Try following.
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var async = require('async');
var result_title = [];
var result_scope = [];
var result_benefits = [];
var result_technical = [];
app.use(express.static(__dirname + '/views'));
app.get('/product1', function(req, res){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('products.db');
var check;
db.serialize(function() {
db.each("SELECT title, scope, body, technical_information FROM products", function(err, row) {
result_title.push(row.title);
result_scope.push(row.scope);
result_benefits.push(row.body);
result_technical.push(row.technical_information);
},function(err, rows){
if(err){
// handle error
}
res.render("index", {title:result_title[0], scope:result_scope[0],benefits:result_benefits[0], technical_information:result_technical[0]});
});
});
});
app.listen(8080);

Related

req.cookies returns undefined but cookies are set

I am using cookie-parser in my express app. When the root page is requested I set a random number on the cookie using res.cookie(name, value) and it sets it fine (I checked on my browser console). But when I try to log req.cookie it always returns undefined.
Here's my code:
routes.js
var express = require('express')
var router = express.Router()
var movieTrailer = require('movie-trailer');
var Promise = require('bluebird');
var logs = require('log-switch');
var fs = require('fs');
//var cookieParser = require('cookie-parser');
//Setup x-ray for scraping
var Xray = require('x-ray');
var x = Xray();
var debug = false;
router.get('/', (req, res) => {
console.log('Page requested!');
console.log('Cookies: ', req.headers.cookies); // For some reason this returns undefined
var scrapeMovies = function(){
return new Promise((resolve, reject) =>{
fs.readFile('moviesRT.json', (err,data) =>{
var movies = JSON.parse(data);
resolve(movies);
});
});
};
scrapeMovies().then(
movies => {
var randomInt = Math.floor(Math.random() * movies.length);
res.cookie('randomInt', randomInt);
var randomMovie = movies[randomInt];
movieTrailer(randomMovie.title, (err, url) =>{
console.log('Requesting trailer: ', randomMovie.title);
if(err) throw err;
var embedUrl = url.replace('watch?v=','embed/');
console.log('Video ID: ', url.slice(32,url.length));
randomMovie.trailerURL = embedUrl; //Add the embed URL to the randomMovie object before rendering it
res.render('main',randomMovie,
(err, html) =>
{
if(err) throw err;
console.log('Rendering...');
res.send(html);
console.log("Done!");
});
});
});
});
module.exports = router;
app.js
const express = require('express');
//Define app and settings
const app = express();
const exphbs = require('express-handlebars');
var cookieParser = require('cookie-parser');
const port = 3000;
var routes = require('./routes');
var debug = true;
app.use('/', routes);
app.use(express.static('public'));
app.use(cookieParser());
//app.use(cookieParser());
//View engine
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.listen(port, function () {
console.log(`Server Starts on ${port}`);
if(!debug) logs.disable(); //Disable logging if debug variable is false
});
You either want to check req.headers.cookie which will be set by express.
Or if you want to use the the parsed result of the cookie-parse middleware that is stored inreq.cookies then your problem is the order in which you register your routes and the middleware.
app.use('/', routes);
app.use(express.static('public'));
app.use(cookieParser());
The parsing of the cookie is done after the routes in routes have ben executed.
You need to move the cookieParser() before the route where you want to use it.
app.use(cookieParser());
app.use('/', routes);
app.use(express.static('public'));
This solved my problem:
Basically when you are sending a request to the server from client-side, make sure you add withCredentials: true. For example
{
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json'
}),
'withCredentials':true
};
This happened to me, when I sent a PUT request from the client-side (Angular) without passing the body object.
I was doing this (second argument missing):
requestBranchEditPermission() {
return this.http.put<IPutProfile>(`${this.api}/some-endpoint`, this.options).toPromise();
}
instead of this:
requestBranchEditPermission() {
return this.http.put<IPutProfile>(`${this.api}/some-endpoint`, {}, this.options).toPromise();
}
You will need to read the cookies as req.cookies['cookie-name'] and set the cookies as resInit.cookie('cookie-name', 'cookie-value')
This worked for me
in the frontend add credentials : 'include' as an option to your fetch API
A more elaborated code below for a get request
fetch('url', {credentials: 'include'})
.then(res => res.json())
.then(data => //do something with the data)
.catch(err => console.log(err.message));

Inserting multiple rows dynamically in mysql database node js?

I am trying to insert multiple rows in mysql database using node js.The idea is that I have four arrays which has 20 values each. My goal is to dynamically insert all the values in my database using node js. Now, I am a bit confused how I should go about it.
This is my server file-
server.js -
const express = require('express');
const app = express();
var db = require("./DatabaseConfig.js");
var cookieParser = require('cookie-parser');
var path = require('path');
var bodyParser = require('body-parser');
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.get('/', function (req, res) {
res.send('Hello World!')
});
app.listen(4000, function () {
console.log('Example app listening on port 4000!')
});
app.get("/home",function(req,res){
res.render("Home.ejs");
});
app.post("/home",function(req,res)
{
var data = JSON.parse(req.body.info);
console.log(data.length);
var counter = [];
var publicationtitle=[];
var publicationdate =[];
var publicationlink=[];
for(var i=0;i<data.length;i++)
{
counter.push(0);
publicationtitle.push(data[i]["title"]);
publicationdate.push(data[i]["pubDate"]);
publicationlink.push(data[i]["link"]);
}
var res = db.dbconfig();
var values = [
publicationtitle, publicationlink,publicationdate,counter
];
console.log("values",values);
db.insertrecord(values);
values=[];
});
DatabaseConfig.js
var mysql = require('mysql');
var con = mysql.createConnection({
host : 'localhost',
user : '****',
password : '****',
database : 'test',
multipleStatements: true
});
var values = [];
module.exports = {
dbconfig: function(error) {
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
},
insertrecord:function(values){
var sql = "INSERT INTO rsscontent (title,link,date,count) VALUES ?";
con.query(sql,[values], function(err) {
if (err) throw err;
con.end();
});
}
};
Any suggestions or advise will be highly appreciated.
You can build your query and values like this:
let placeholder = users.map(() => "(?, ?)").join(",");
let query =
`INSERT INTO ${TABLE_NAME.USER}
(id, username)
VALUES ${placeholder}`;
let values = [];
users.forEach(user => {
values.push(user.id);
values.push(user.username);
});
Been using this and it worked fine.
Other than what have been answered, your INSERT statement is bound to throw error since date is a keyword and should be escaped like
var sql = "INSERT INTO rsscontent (title,link,`date`,count) VALUES ?";

http request won't execute

I am a real noob in JS and Node and am trying to render a JADE view from JSON received from a REST API. When i run the http.request as a standalone it works just fine, but when i start adding modules and the render stamens, I cannot get the http request function to execute.
When i run it in debug it just skips to the end statement. i cannot figure out why.
any help would be really appreciated TIA.
var http = require('http');
module.exports = function() {
var options = {
host: '41.193.214.130',
port: 2510,
path: '/eiftidemo/clt_list',
method: 'GET'
};
var clientsDatag;
http.request(options, function(res) {
var body = '';
//none of these statemnst excecute
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
var clientsData = JSON.parse(body);
var clientsDatag = clientsData;
// this stament doesn't execute either
debugger;
});
}).end();
debugger;
res.render('listlxr', {
details: clientsDatag
});
};
here is the calling script:
var express = require('express');
var bodyParser = require('body-parser');
var tweetList = require('./tweet-list');
var clientList = require('./lxr-clients')
var app = express();
app.set('view engine', 'jade');
app.use(bodyParser.urlencoded({
extended: false
}))
app.get('/', function(req, res) {
res.render('index');
});
app.post('/get_tweets', function(req, res) {
var screen_name = req.body.handle;
var tweets = tweetList(res, screen_name);
});
app.get('/get_clients', function(req, res) {
var clientd = clientList(res, req);
});
var server = app.listen(3000, function() {
console.log('Our App is running at http://localhost:3000');
});
many thanks to anyone who can help
app.get('/get_clients', function(req, res) {
var options = {
host: '41.193.214.130',
port: 2510,
path: '/eiftidemo/clt_list',
method: 'GET'
};
http.request(options, function(details) {
res.render('listlxr', {
details: details
});
});
});
Try adding an error-handler and see if you get anything there:
var request= http.request(options, function(res) {...});
request.on('error', function(err){
// Handle error
});

Loading JSON files during Express app initialization

I have a movie-finding app that makes API calls in the backend. During initialization I need to load some JSON files: one (lang.json) contains a list of languages for searching purposes, the other (stored in the config variable) is used to get a link to the movie poster.
How would I ensure the loading of these files is completed before an HTTP request is made? One solution I can think of involves putting the calls to app.get() and app.listen() inside fs.readfile()'s callback. But is there a better way? Web development is totally new to me.
var express = require('express');
var app = express();
var fs = require('fs');
var request = require('request');
var merge = require('merge');
require('dotenv').config();
var apiKey = process.env.API_KEY;
var config = {};
app.use(express.static('view'));
// TODO load config and lang before below code
app.get('/lang', function(req, res) {
fs.readFile('lang.json', function(err, data) {
if (err) throw err;
res.json(JSON.parse(data));
});
});
app.get('/genres', function(req, res) {
request.get({
url: 'http://api.themoviedb.org/3/genre/movie/list',
qs: {api_key: apiKey}
}, function(error, response, body) {
res.json(JSON.parse(body).genres);
});
});
app.get('/randomMovie', function(req, res) {
request.get({
url: 'https://api.themoviedb.org/3/discover/movie',
qs: merge(req.query, {api_key: apiKey})
}, function(error, response, body) {
body = JSON.parse(body).results;
var len = body.length;
var i = Math.floor(Math.random() * len);
var movie = body[i];
// movie.poster_path = movie.images.base_url + movie.images.poster_sizes[6] + movie.poster_path;
res.json(movie);
});
});
app.listen(3000, function() {
console.log('server started on port 3000');
});
The easiest way is to just use fs.readFileSync() before your call to app.listen(). For example:
var lang = fs.readFileSync('lang.json');
app.get('/lang', function(req, res) {
res.setHeader('Content-Type', 'application/json');
res.send(lang);
});
// ...
Just be aware that the contents of lang will not automatically update if the contents of lang.json change on disk during the lifetime of your node process.

How to use express.js with native mongoDB driver

I struggle while trying to do a simple mongoDB query from within my express app:
app.js
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var mongourl = ''; // omitted on SO
var MongoClient = require('mongodb').MongoClient;
var dbInstance;
MongoClient.connect(mongourl, function(err, db) {
db.on('open',function(){
dbInstance = db;
})
});
app.get('/', routes.index(dbInstance));
http.createServer(app).listen(app.get('port'), function(){
});
routes/index.js
exports.index = function(db){
return function(req,res){
}
};
Do i understand correctly that the exports.index' paramter is a database instance? If so, why can't i do db.getCollectionNames()?
How would i work with the database instance in my route?
node.js is asynchronous. This means that db and so dbInstance do not exist after the Mongoclient.connect() function call, but within the callback. So your code has to look like:
MongoClient.connect(mongourl, function(err, db) {
...
app.get( '/', routes.index( db ) );
...
});

Categories

Resources