I'm trying to build my first node app. My app.js file is shown below. I want to access this from aother module by doing 'app = require('app')'. I then want to access app.app, app.dbConn and app.models
The problem is that when I require this module, app.models is not present on the resulting object.
var express = require('express');
var path = require('path');
var orm = require('orm');
var settings = require('./config/settings');
var mainRouter = require('./config/routes');
var environment = require('./config/environment');
var db = require('./config/db');
var auth = require('./modules/auth');
module.exports = new function(){
this.app = express();
// middlewares must be added in order - start with the basics
environment(this.app);
if (process.env.TESTING) { dbSettings = settings.dbTesting; }
else { dbSettings = settings.db; }
// add models to the request early in the middleware chain
this.dbConn = orm.connect(dbSettings, function(err){
if (err) return console.error('DB Connection error: ' + err);
else{
this.models = db.init(this.dbConn);
this.app.use(function(req,res,next){
req.models = this.models;
next();
});
passport = auth.init(this.models);
authRouter = auth.router(passport)
this.app.use('/users', authRouter);
this.app.use(mainRouter);
}
}.bind(this));
this.app.listen(settings.port);
console.log('Server started... listening on port ' + settings.port)
}
The only way to implement what I wanted was with a function that takes a callback, in the end I rewrote my code thus:
var express = require('express');
var path = require('path');
var orm = require('orm');
var settings = require('./config/settings');
var mainRouter = require('./config/routes');
var environment = require('./config/environment');
var db = require('./config/db');
var auth = require('./modules/auth');
var app;
module.exports = function(cb){
app = express();
// middlewares must be added in order - start with the basics
environment(app);
if (process.env.TESTING) { dbSettings = settings.dbTesting; }
else { dbSettings = settings.db; }
// add models to the request early in the middleware chain
dbConn = orm.connect(dbSettings, function(err){
if (err) return console.error('DB Connection error: ' + err);
else{
models = db.init(dbConn);
app.use(function(req,res,next){
req.models = models;
next();
});
passport = auth.init(this.models);
authRouter = auth.router(passport)
app.use('/users', authRouter);
app.use(mainRouter);
cb({
dbConn: dbConn,
app: app,
models: models
});
}
});
}
if (!process.env.TESTING) {
module.exports(function(server){
server.app.listen(settings.port);
console.log('Server started... listening on port ' + settings.port)
});
}
app.models is defined only once database connection is completed: you cannot use it right away after requiring the module. You should provide an entry point that accepts a function to call once the connection is ready and call this function inside the orm.connect callback.
Even the "server started" message is a bit misleading as it's shown before the server can actually do anything because the function passed to orm.connect has not been called yet.
app.models is never defined so it is never available.
Instead, try
app.set('models', db.init(this.dbConn);
Related
Iam trying to provide a new route for my conversation application where it should accept the parameters passed along with the route should be accepted and can be used in client side.But I couldnt figure out why basic .get() is not working ,where Iam unable to render the html.
'use strict';
var express = require('express'); // app server
var bodyParser = require('body-parser'); // parser for post requests
var Conversation = require('watson-developer-cloud/conversation/v1'); // watson sdk
var bodyParser = require('body-parser');
var app = express();
app.use(express.static('./public')); // load UI from public folder
app.use(bodyParser.json());
app.get('/:id',function(req,res){
var userid = req.params.id;
var pid = req.query.pid;
res.sendFile(__dirname,'/public/index.html');
});
module.exports = app;
On my localhost:3000 index file is getting loaded but for something like localhost:3000/3405?pid=CBM it is not loading.
Then I have a js file on client side which would require these two values id and pid.For now I just hardcoded.But how can I use these values to client side js file..Can someone help me how can I do this...
Thanks
Updated :Adding my client side js file
var Api = (function() {
var messageEndpoint = '/api/message';
var emp = {
"pid": "CBM",
"id": "3405",};
return {
sendRequest: sendRequest,
modifytext: function(intent, text) {
if (intent == "Hello") {
console.log(text, "Inside intent");
for (var key in emp) {
var tempKey = '{{' + key + '}}';
var tempValue = emp[key];
text = replace(text, tempKey, tempValue);
console.log("came back");
}
}
return text;
console.log(text,"Final text");
}
};
function replace(text, originalString, replaceText) {
console.log("Reached replace functions", text, originalString, replaceText);
if (replaceText)
text = text.replace(originalString, replaceText);
else
text = text.replace(originalString, "");
return text
}
}());
This is incorrect:
res.sendFile(__dirname,'/public/index.html');
It should be this:
res.sendFile(__dirname + '/public/index.html');
Or (a bit more robust):
const path = require('path');
...
res.sendFile(path.join(__dirname, 'public/index.html'));
As a side note: apparently, if you pass a directory name to res.sendFile(), it will send back a 404 response. Not sure that the rationale behind that is.
Send a parameter(URL) from another script through recursion to this script.
var express = require('express');
var request = require('request');
var cheerio = require('cheerio');
var mongodb = require('mongodb');
var app = express();
var MongoClient = mongodb.MongoClient;
// Connection URL. This is where your mongodb server is running.
var murl = 'mongodb://localhost:27017/getData';
url = '';
app.get('/getData', function(req, res){
firstCall(req,res)
//console.log("cookie",req.cookies);
})
var firstCall = function(req, res, data){
console.log("URL: ", url);
res.send('Check your console!');
}
app.listen('3000')
console.log('Magic happens on port 3000');
module.exports = function(app) {
app.get('/getData', function() {});
};
I want this code to act as backbone or logic board. And some other file should be able to trigger this logic board file by adding the URL to this file.
Like we pass parameters to function to call. How do I do it here.
This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Closed 6 years ago.
MY ACTUAL CODE (THAT WORKS!)
I've created a function with callback to create sessions and generate tokens for OpenTok, that exports itself to application.
The function
//Dependencies
var opentok = require('./ot').opentok;
var apiKey = require('./ot').apiKey;
var apiSecret = require('./ot').apiSecret;
//Define variables
var sessionId;
var token;
//Define create newSession function
var newSession = function(callbackS){
//Create Session (That allows to OpenTok)
opentok.createSession({mediaMode:"relayed"}, function(err, session){
if(err) throw err;
else {
//Define session object
var objSession = {};
//Obtain sessionId
objSession.sessionId = session.sessionId;
//Call generate token function
newTok(objSession,callbackS);
}
});
}
//Define generate token function
var newTok = function(obj, fn){
//Generate token (that allows to OpenTok)
token = opentok.generateToken(obj.sessionId);
//Store object (obj.tokenId) in token variable
obj.tokenId = token;
//Define "obj" in function context
fn(obj);
}
//Export new Session with sessionId and token
module.exports.credentials = newSession;
The APP
// Dependencies
var express = require('express');
var server_port = process.env.PORT || 3000;
var apiKey = require('./ot').apiKey; //Obtain default apiKey
var credentials = require('./credentials').credentials(fun);
//function that was export from "credentials" (the function)
function fun(obj) {
//Define app
var app = express();
//Use "public" static folder
app.use(express.static(__dirname + '/public'));
//Initialize the app
init();
//Routing
app.get('/', function(req, res) {
//Rendering variables in views
res.render('index.ejs', {
apiKey: apiKey,
sessionId: obj.sessionId,
token: obj.tokenId
});
});
//Define Init
function init() {
app.listen(server_port, function() {
console.log('The app is running in localhost:' + server_port);
});
}
}
THAT I WANT:
How I could convert my function that creates sessions and generates tokens in a promise that I can use into my app?
UPDATE (08/01/2016) (14:53 VET)
I've exported the function module in my app as follow:
// Dependencies
var express = require('express');
var server_port = process.env.PORT || 3000;
var apiKey = require('./ot').apiKey; //Obtain default apiKey
var credentialsPromise = require('./credentialsPromise').credentialsPromise(); //Obtain the promise
console.log(credentialsPromise);
And throw in console:
Promise { <pending> }
How I should use my promise in my app?
The minimal approach is as follows (see *** comments):
var newSession = function(){
// *** Return a promise
return new Promsie(function(resolve, reject) {
opentok.createSession({mediaMode:"relayed"}, function(err, session){
// *** Reject on error
if (err) {
reject(err);
} else {
var objSession = {};
objSession.sessionId = session.sessionId;
// *** Have newTok call `resolve` with the object when done
newTok(objSession, resolve);
}
});
});
};
Note that I didn't promise-ify newTok, though we could. It's not clear why newTok accepts a callback when nothing in it is asynchronous and it's a private function.
Using it looks like this:
newSession(/*...parameters...*/).then(
function(result) {
// All is good, use result
},
function(err) {
// Error occurred, see `err`
}
);
I'm fairly new to node.js and recently started to make some modules. However I've come to a point where communication between modules is required. Since this is not a problem I've encountered in the past I'm stuck with finding a clean solution.
This is the boilerplate I currently got (Left out some checks to make the code a bit smaller). The basic idea atm is joining any irc channel given by an http post.
bot.js
//Include services
var Webservice = require('./Webservice');
var Ircservice = require('./Ircservice');
//Create service instances
var webservice = new Webservice();
var ircservice = new Ircservice();
//Initialize services
webservice.init(1337);
ircservice.init('alt-irc.snoonet.org', 80, 'User');
//Handle events
ircservice.on('irc-registered', function(msg){
console.log(ircservice.connected);
ircservice.joinChannel('#testchannel')
});
ircservice.on('irc-join', function(channel){
console.log('Successfuly joined: ' + channel);
});
webservice.on('web-join', function(streamer){
ircservice.joinChannel('#' + streamer);
});
Webservice.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
app.use(bodyParser.urlencoded({
extended: true
}));
var Webservice = function(){
EventEmitter.call(this);
};
Webservice.prototype.init = function(port){
app.listen(port, function () {
console.log('Webserver listening on ' + port);
});
this.initRoutes();
};
Webservice.prototype.initRoutes = function(){
var self = this;
//join a irc-channel
app.post('/join', function (req, res) {
var streamer = req.body.name;
self.emit('web-join', streamer);
res.send('Received')
});
};
util.inherits(Webservice, EventEmitter);
module.exports = Webservice;
Ircservice.js
var irc = require('irc');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var Ircservice = function(){
EventEmitter.call(this);
}
Ircservice.prototype.init = function(server, port, nick){
this.client = new irc.Client(server, nick, {
port: parseInt(port)
});
this.initListerners();
};
Ircservice.prototype.initListerners = function(){
var self = this;
this.client.addListener('message', function (from, to, message) {
console.log(from + ' => ' + to + ': ' + message);
});
this.client.addListener('join', function(channel, nick, message){
self.emit('irc-join', channel);
});
};
Ircservice.prototype.joinChannel = function(channel){
this.client.join(channel, null);
};
util.inherits(Ircservice, EventEmitter);
module.exports = Ircservice;
This example works perfectly, but as you can see the communication between my webservice and ircservice is handled by the bot.js. While this is perfectly fine for this example, I cannot use this method whenever I want.
Let say in the future I want to keep a list in my ircservice of all channels he has joined and display this through a webpage. I could keep a local array on my ircservice and on the join event add that channel to the array. But how do I continue on the webservice end. I can write an endpoint '/getchannels' but my webservice itself is not aware of the ircserver to get the channels (ircservice.getChannels or something similar) and firing an event in my web request doesn't feel like the way to go.
One solution that came up in my mind was passing the instances of the services to each other like webservice.setIrcservice(ircservice) and the other way around in the bot.js. But this feels like dirty code and a hard depency.
So how can I communicate between modules when I need data instantaneously and events are no option?
I have 3 node js files :
mysqlconnection.js to store the database connection properties:
var mysql = require('mysql');
var cjson = require('cjson');
var yaml_config = require('node-yaml-config');
// project files
var config = yaml_config.load(__dirname + '/billingv2.yaml');
exports.execute = function(callback){
var connection = mysql.createConnection(
{
host : config.host,
user : config.user,
password : config.password,
database : config.database,
}
);
connection.connect();
return callback(null,connection);
}
subscriptionRestService.js to handle the REST api calls:
var express = require('express');
var app = express();
app.use(express.bodyParser());
var fs = require('fs');
// Project files
var mysql = require('./mysqlRestService.js');
// Get Resource Subscription data by Resourceuri
app.post('/pricingdetails', function(req, res) {
var workload = req.body;
if(workload.elements && workload.elements.length > 0)
{
var arr = [];
for(var index in workload.elements)
{
arr[index] = workload.elements[index].uri;
}
var resourceIdentifiers = arr.join(',');
}
console.log(resourceIdentifiers);
mysql.getPricingDetail(function(resourceIdentifiers,callback){
});
});
mysqlRestService.js to handle mysql queries/stored procedures:
// packages
var mysql = require('mysql');
var cjson = require('cjson');
var fs = require('fs');
var yaml_config = require('node-yaml-config');
// project files
var dbconnection = require('./mysqlconnection');
exports.getPricingDetail = function (resourceIdentifiers,callback){
console.log('entered into mysql function');
console.log(resourceIdentifiers);
var pricingDetail = {};
dbconnection.execute(function(err,response){
if(err){
throw err;
}
else
{
var selectqueryString = "call SP_ExposePricingDetailforUI('" + resourceIdentifiers + "')";
response.query(selectqueryString, function(err,pricingDetail){
if(err) {
throw err;
}
else
{
console.log(pricingDetail);
pricingDetail = pricingDetail;
}
});
}
});
//console.log('printing pricing details');
//console.log(pricingDetail);
};
problems faced
Unable to send the variable resourceIdentifiers from subscriptionRestService to mysqlRestService.js
Unable to return the pricingdetail from mysqlRestService.js to calling function in subscriptionRestService.
Any guidance greatly appreciated.
Unable to send the variable resourceIdentifiers from subscriptionRestService to mysqlRestService.js
Well, you didn't send it. It currently is a parameter of your callback function in the invocation, not an argument for the parameter of getPricingDetails. Use
mysql.getPricingDetail(resourceIdentifiers, function callback(result){
// use result here
});
Unable to return the pricingdetail from mysqlRestService.js to calling function in subscriptionRestService.
I've got no idea what pricingDetail = pricingDetail; was supposed to do. You have to call (invoke) back the callback here! Use
callback(pricingDetail);