I'm currently working with Node.js, Express.js and Jade. My database is MySQL. I'm new to node.js, so I thought I try something very easy: Displaying some data from the database in a table in the browser.
Unfortunately it still doesn't work. I can display data on an free port but not where I need it - on port 3000. And I also can't work with the response itself. This is one of the "solutions" or ideas I had. Maybe there is a problem with the asynchronous call? I simply have no idea.
Here is my code:
routes.js
var express = require('express');
var controller = express.Router();
var dataModel2 = require('../models/rooms');
controller.get('/rooms', function(req, res, next) {
var rooms = dataModel2();
res.render('rooms', {
items: rooms
});
});
module.exports = controller;
models/rooms.js
var rooms;
var connection = require('./databaseConnection');
var http = require('http');
rooms = function() {
http.createServer(function (request, response)
{
console.log('Creating the http server');
connection.query('SELECT * FROM rooms', function(err, rows, fields)
{
response.writeHead(200, { 'Content-Type': 'application/json'});
var room = response.end(JSON.stringify(rows));
return room;
});
});
module.exports = rooms();
models/databaseConnection.js
var mysql = require('mysql');
module.exports = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'raspi_key_royal'
});
rooms.jade
extends layout
block content
div(id="bodyRoyal")
table(border='1')
thead
tr
th ID
th Name
tbody
each item in items
tr
td=item.rid
td=item.name
I splitted the functions a bit because there are some other sections like "persons" etc. I tried to insert console.logs in the rooms.js but that doesn't seem to work.
I also thought I could save the response into a variable so that I can work with it somewhere else.
Thank you for every help and hints!
Steffi
Something like this should do it:
var express = require('express'),
app = express(),
connection = require('./databaseConnection');
app.get('/rooms', function (req, res) {
connection.query('SELECT * FROM rooms', function(err, rows, fields)
{
res.render('rooms', {
items: rows
});
});
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
This is from the express site...http://expressjs.com/starter/hello-world.html
app.listen(3000, ...
is the how to configure a it to a specific port (in this case 3000).
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
Related
I would use sockets in a separate route file .
I'm using the method mentioned in this answer : Express 4 Routes Using Socket.io
I have copied exactly the same logic. In server file :
var http = require("http");
var admin = require('firebase-admin');
var firebase = require("firebase");
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var port = process.env.app_port || 8080; // set our port
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var server = app.listen(port);
var io = require("socket.io")(server);
var routerProj = require("./routes/routes")(io);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,*");
next();
});
var config = {
.... DB Configuration ....
};
firebase.initializeApp(config);
var serviceAccount = require("./ServiceAcountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://datatable-18f93.firebaseio.com"
});
io.on("connection", function (client) {
console.log("Un client est connecté !");
//routerProj(client);
});
app.use("/v1", routerProj, function (req) {
//Create HTTP server and listen on port 8000 for requests
});
My connection socket is working and the console.log runs in terminal
routes.js file
var express = require("express"); // call express
var router = express.Router(); // get an instance of the express Router
var admin = require("firebase-admin");
var returnRouter = function (client) {
router.use(function (req, res, next) {
// do logging
client.on('save-message', function (socket) { console.log("heheyy") })
});
router
.route("/")
.get(function (req, res, err) {
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.once("value", function (snapshot) {
var list = [];
snapshot.forEach(function (elem) {
list.push(elem.val());
})
list = JSON.stringify(list);
//list = JSON.parse(list)
console.log(err);
//console.log(JSON.stringify(list))
res.send(list);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
res.status(500).send(errorObject.code);
});
});
router
.route("/")
.post(function (req, res, err) {
console.log(req.body);
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
ref.push(
{
"text": req.body.text
}
);
});
return router;
}
module.exports = returnRouter;
save-message is emit in Angular when my arr is running :
ngOnInit() {
this.socket.emit('save-message', { room: "hello" });
}
Save-message event is not getting read neither the routes file, In my angular application services does not get data from routes. and console.log in get and post routes does not work.
My question is how to get sockets working in a reparate file ?
You should move the socket.io listener outside of the express use route. It's not really clear why you would want it there as it will register a new listener every time someone makes a request to your v1 endpoint.
You likely aren't seeing the messages because the listener does not register until someone makes a request to the v1 endpoint and the client already sent its message.
var returnRouter = function (client) {
// do logging
client.on('save-message', function (socket) {
console.log("heheyy");
});
...
};
var express = require('express');
var app = express();
var pg = require('pg');
var connectionString = "postgresql://postgres:sujay123#localhost:3001/redc";
app.use(express.static('public'));
app.get('/index.html', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
})
app.get('/process_get', function (req, res) {
response = {
name:req.query.name,
lat:req.query.lat,
long1:req.query.long
};
console.log(response);
res.end(JSON.stringify(response));
var client = new pg.Client(connectionString);
client.connect();
console.log("connect");
console.log("INSERT INTO data(name, latitude,longitude) values('"+req.query.name+"',"+req.query.lat+","+req.query.long+")");
var i = client.query("INSERT INTO data values('"+req.query.name+"',"+req.query.lat+","+req.query.long+")");
console.log(i);
console.log("Query Inserted")
})
var server = app.listen(3001, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
I am getting this code and running but when i check the db the insert query has not worked and th values in the 3 paramters are coming of name, lat and long just the query isnt working i guess.
Yes your syntax for insert is wrong. The query that you are logging in console looks correct, but it's different from the string you're using in the database query.
I am building a real-time notification system using socket.io. This is my server-side code at the moment:
bin/www:
var app = require('../app');
var server = http.createServer(app);
var io = app.io
io.attach(server);
server.listen(port, function(err) {
if (err) console.log(err);
console.log('Listening on port ' + port + '...');
});
app.js:
var socket_io = require('socket.io');
var express = require('express');
var app = express();
var io = socket_io();
app.io = io;
require('./config/socket')(app.io);
config/socket.js:
var User = require('../controllers/user');
module.exports = function (io) {
io.on('connection', function (socket) {
console.log('Socket.io connected');
socket.emit('connection', "Connection created.");
socket.on('send notification', function(data) {
User.createNotification(socket.request.user, data);
});
});
};
routes/index.js:
var express = require('express');
var User = require('../controllers/user');
var router = express.Router();
router.post('/order', User.order);
module.exports = router;
controllers/user.js:
var User = require('../models/user').model;
var io = require('socket.io');
module.exports = {
order: function(req, res) {
/* some create order code */
io.emit('send notification', 'Your order was successful!');
res.sendStatus(200);
}
}
I keep getting the error TypeError: io.emit is not a function whenever I try to call the route POST /send even though I am clearly initiating socket.io in my app.js and bin/www files and requiring it in controllers/user.js. All the examples I've seen online emit notifications from within this part:
io.on('connection', function (socket) {
socket.emit(event, msg);
});
but I want my notifications to be triggered from the middleware so I can send custom notifications to the user when certain events happen in the application backend.
Try the following instead:
io.on('connection', function(socket){
socket.on('xxx', function(obj){
io.emit('xxx', {xxx: xxx})
})
})
This should suppress your TypeError:.
I'm trying to modularize my application files and I'm having problems with Socket.io. I would like to use the io inside my routes.js. Something like this:
var router = require('express').Router();
var io = require('./sockets/my-io');
router.get('/', function(req, res) {
io.emit('request-detected');
});
module.exports = router;
But I can't do, because the socket.io needs the app server, and when I'm inside the routes.js file, the app server is not listening or being exported yet.
Can you give me a solution, or any other approach to this problem?
Here's what I have, and if it's possible, I would like to keep the file structure:
app.js
var app = require('express')();
var routes = require('./routes');
/* ... */
app.use('/contacts', routes);
module.exports = app;
bin/www
#!/usr/bin/env node
var app = require('../wallet');
var server = app.listen(port, function() {
debug('Express is listening o port ' + port);
});
routes.js
var router = require('express').Router();
router.get('/', function(req, res) {
console.log('hey');
});
module.exports = router;
You can do it by passing the io variable to your routes module.
bin/www
#!/usr/bin/env node
var app = require('./app');
var server = app.listen(3000, function() {
console.log('Express is listening on port 3000');
}); // start the server
var socket = require('./socket')(server); // require socket.io code
var routes = require('./routes')(socket); // require routes
app.use('/', routes);
app.js
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.set('views engine', 'ejs');
app.set('views', __dirname + '/');
module.exports = app;
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newEvent', function (data) {
console.log(data);
});
});
return io;
}
module.exports = init;
routes.js
var express = require('express');
var route = express.Router();
function init(io) {
route.get('/', function (req, res) {
res.render('index.ejs', {});
setTimeout(function() {io.emit('newEvent', {message: "Hi from the server"})}, 2000);
});
return route;
}
module.exports = init;
The code above worked for me. However, I'm not sure why you want to do that.
Inside the router, you still have full control of what you want to send to the user via html, so you can just add the data to the html directly.
The idea of socket.io is that you can send data between the client and back once he has loaded the html and established a connection to your server with socket.io.
As you can see in the routes.js, I had to add a timeout to the emit. This is because the socket event will be emit before the browser has reloaded the page. In my case the browser logged the event and then immediately refreshed, losing the data you just sent.
Another problem is that you don't know anything about the socket of the client that is requesting the page because he hasn't connected yet. This means that calling io.emit() will send the event to all connected sockets.
As I said, this really depends on what exactly you want to do.
EDIT:
Instead of updating your contacts using ajax, you can do that with socket.io.
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newContact', function (data, callback) {
// add data.contactName to db
// after adding something, you use the callback to
// send the added data back to the client
// callback(newContact);
});
});
return io;
}
module.exports = init;
index.html
<script type="text/javascript" >
var socket = io();
// call this emit when the user wants to add a contact
socket.emit('newContact', {contactName: name}, function(newContact) {
// here you will get the result from the server and you can
// update the html with jquery for example
});
</script>
If i understand your question correctly ,maybe you can try this way.
in your routes.js file
var app = require('./app');
var server = require('http').createServer(app);
var io = require('./sockets/my-io')(server);
var route = app.Router();
in your app.js file
var port = process.env.PORT || 3000;
app.listen(port,function(){
console.log('server on port ' + port)
})
I am wondering if someone could help me point out how to cache a resource in express/node on startup of the web server. The myCol.find is very expensive, so I would like to just run it once on startup, and cache the result for all subsequent requests. Is there a startup step I can tie into? Can this be done synchronously before the server starts accepting requests?
I have the code below, but would like to reference a cached variable instead of the mongo db
var express = require('express');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');
var myCol = require('./customModule');
var port = process.env.PORT || 8080;
var router = express.Router();
router.get('/test/:testId', function(req, res) {
myCol.find(function(err, allResults) {
res.json(allResults);
});
});
app.use('/api', router);
app.listen(port);
Yep, you just need to make sure your server starts listening after you've fetched your results through myCol.find():
var express = require('express');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');
var myCol = require('./customModule');
var port = process.env.PORT || 8080;
var router = express.Router();
var myResultsCache;
router.get('/test/:testId', function(req, res) {
res.send(myResultsCache);
});
app.use('/api', router);
myCol.find(function(err, allResults) {
//you should add some error handling here
myResultsCache = allResults;
app.listen(port);
});
You could swap the order of myCol.find and the route handler, so that the relevant code would be:
myCol.find(function(error, results) {
if (error) throw error;
router.get('/test/:testId', function (request, response) {
response.json(results);
});
});
This is still asynchronous, but the server would only be able to respond after the find operation has been done.