Node.js: view data in controller called from model [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I want to assign data return from the model, then on console.log i only see
undefined
My code is:
var dmodel = require('../models/database');
dmodel.myfunction(request,response, function (err, user) {
console.log(user); // see data
});
Then I repair code:
var dmodel = require('../models/database');
var userinfo;
dmodel.myfunction(request,response, function (err, user) {
userinfo = user;
});
console.log(userinfo); // undefined, not see data
How do it ? Thanks all
This is my function:
module.exports = {
myfunction: function (request,response, callback) {
var query = "select * from mytable";
//call functionexcecute query
executeQuery(query, function (err, rows) {
if (!err) {
var user = rows;
callback(null, user);
} else {
console.log(err);
}
});
}
};

Due to asynchronous nature of javascript, code console.log(userinfo) is getting executed before the callback function is called.
Modified code:
var dmodel = require('../models/database');
var userinfo;
dmodel.myfunction(request,response, function (err, user) {
userinfo = user;
console.log(userinfo);
});
That is, your earlier code was correct. If the value printed is still undefined, that means there is some issue with the definition of function executeQuery.

you can use a .then promise which will wait for the first function to complete its execution
var dmodel = require('../models/database');
var userinfo= {};
dmodel.myfunction(request,response, function (err, user) {
userinfo = user;
return userinfo;
}).then(function(data){
console.log(userinfo);
})

Related

How to access a variable defined in the request function outside the function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
in this case I would like to access to data:
const request = require('request');
const { url } = require("inspector");
request(`https://api.0x.org/swap/v1/tokens`, { json: true }, (err, res, body) => {
if (err) { return console.log(err);
}
let data = body;
});
console.log(data)
console.log(data) return ReferenceError: data is not defined
You cannot access data unless you were to define it outside of your function. Update the variable data within your function via this.data = body;
Something like this.
const request = require('request');
const { url } = require("inspector");
let data = "";
request(`https://api.0x.org/swap/v1/tokens`, { json: true }, (err, res, body) => {
if (err) { return console.log(err);
}
this.data = body;
});
console.log(this.data)

Pass object from SQL query function to a separate function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I'm new to node and promises. I have two files - server.js and db.js
server.js imports db.js as modules.
I'm fetching some data from a SQL database in a db.js module and I'm trying to pass that data to a function in server.js.
I've successfully fetched the data from database, but when I try to pass it to the function in server.js, it only returns an undefined value.
Here's the code
server.js
const db = require('./db.js');
app.post('/api/trigger-push-msg/', function (req, res) {
return getSubscriptionsFromDatabase()
.then(function(subscriptions) {
// Do something
});
});
function getSubscriptionsFromDatabase() {
return new Promise((resolve, reject) => {
let subscriptions = db.getSubscriptions();
console.log(subscriptions); // this only prints "undefined"
if (subscriptions != undefined) {
resolve(subscriptions);
} else {
reject("No"); // this executes
}
})
}
db.js
module.exports = {
getSubscriptions: function() {
var sql = "SELECT * FROM subscriptions";
con.query(sql, function(err, result) {
if (err) throw err;
console.log(result); // this prints the same result as I want
return result;
})
}
}
getSubscriptions doesn't have a return statement
and considering that there's some async content in it you should wrap all inside a promise and trigger the subsequent logic only after it resolves.
module.exports = {
getSubscriptions: function() {
var sql = "SELECT * FROM subscriptions";
return new Promise(function(resolve, reject){
con.query(sql, function(err, result) {
if (err) return reject(err);
resolve(result);
})
})
}
}
then:
function getSubscriptionsFromDatabase() {
return db.getSubscriptions()
.then(function(subscriptions){
return subscriptions;
})
}
and in your route:
app.post('/api/trigger-push-msg/', function (req, res) {
getSubscriptionsFromDatabase()
.then(function(subscriptions) {
res.send(subscriptions);
})
.catch(function(err){
res.sendStatus(500);
})
});

Function not returning object retrieved from mongodb [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I'm trying to create a function that will query a mongo db and then return the result, then render it on a page.
I'm just currently trying to console.log the objects to find out why this isn't working:
var getMarkets = function (marketID) {
MongoClient.connect('mongodb://localhost:27017/test', function(err, db){
db.collection("new-test-2", function (err, collection) {
collection.find({"ID": parseInt(marketID, 10)}).toArray(function(err, items) {
console.log(items);
return items;
});
});
});
};
router.get('/markets/:marketid', function(req, res, next) {
var marketobj = getMarkets(req.params.marketid);
console.log(marketobj);
res.render('api', { title: 'API', marketid: marketobj });
});
The log nested inside the function works fine, but then the log inside the routing object returns undefined. What's going on here? I have a feeling it has to do with asynchronous callbacks but I'm not able to reason about it.
Thanks a ton.
Use callback function to access data
var getMarkets = function (marketID , callback) {
MongoClient.connect('mongodb://localhost:27017/test', function(err, db){
db.collection("new-test-2", function (err, collection) {
collection.find({"ID": parseInt(marketID, 10)}).toArray(function(err, items) {
console.log(items);
//return callback
return callback(items);
});
});
});
};
router.get('/markets/:marketid', function(req, res, next) {
getMarkets(req.params.marketid , function(marketobj){
if(marketobj){
console.log(marketobj);
res.render('api', { title: 'API', marketid: marketobj });
}else{
// do whatever you want
res.render('api', { title: 'API', marketid: {} });
}
});
});
Mongodb connection and find operations are asynchronous functions. So you need to use callback to return result. Just return inside function doesn't work.
var getMarkets = function (marketID, callback) {
MongoClient.connect('mongodb://localhost:27017/test', function(err, db){
db.collection("new-test-2", function (err, collection) {
collection.find({"ID": parseInt(marketID, 10)}).toArray(function(err, items) {
if(err)
callback(err)
else {
console.log(items);
callback(null,items);
}
});
});
});
};
router.get('/markets/:marketid', function(req, res, next) {
getMarkets(req.params.marketid, function (err, marketobj) {
console.log(marketobj);
res.render('api', { title: 'API', marketid: marketobj });
});
});
You can use promises also.

Method name is not a function

I have problem in calling the method in my module.
There is an errorTypeError: usr.User.getAddress is not a function
I don't know how to fix this I think I have problem in my module code. I want to get the address or the result.
in my main.js
var mysql = require('mysql');
var usr = require('./user');
var useraddress = usr.User.getAddress (id,pool); //this is how I access the method
in my user.js
exports.User = function () {
return {
getAddress: function (userid, pool){
pool.getConnection(function (err, connection) {
var options = {
sql: " select address from user where id = ?
};
var querypos = connection.query(options, [userid], function (err, results) {
if (err) throw err;
});
});
}
};
};
You are exporting User as a factory function which returns an object with getAddress method on it. So you need to invoke (instantiate) User first:
var useraddress = usr.User().getAddress(id, pool);
Another important problem. connection.query request is asynchronous, which means that assigning getAddress result to var useraddress doesn't make sense. Instead you need to either pass callback to getAddress or use Promise pattern (check this post for great deal of details on the topic: How do I return the response from an asynchronous call?).
In your case I think something like this would be a simplest working approach:
exports.User = function () {
return {
getAddress: function (userid, pool){
pool.getConnection(function (err, connection) {
var options = {
sql: "select address from user where id = ?"
};
var querypos = connection.query(options, [userid], function (err, results, callback, errCallback) {
if (err) {
errCallback(err);
}
callback(results);
});
});
}
};
};
and usage:
usr.User().getAddress(id, pool, function(result) {
console.log('Loaded', result);
});
This is because usr.User does not have .getAddress property on it.
To use .getAddress as a property, you need to export User as an object instead.
exports.User = {
getAddress: function (userid, pool){
pool.getConnection(function (err, connection) {
var options = {
sql: " select address from user where id = ?
};
var querypos = connection.query(options, [userid], function (err, results) {
if (err) throw err;
});
});
}
};
};
Now it does.

Thinking OOP in JavaScript / Node.js

I understand well the concepts of OOP and prototypal inheritance in JavaScript, but sometimes, I wonder how to make use of these in real world applications.
I'll take as an exemple a simple(istic) contact management web application I pushed on GitHub a couple of months ago.
In the main handler mainly reside functions:
var UserModel = require('../models/userModel.js');
var checkObjectId = new RegExp('^[0-9a-fA-F]{24}$');
var root;
exports.getContacts = function(request, response) {
var id = JSON.parse(request.params.user)[0];
// validate
if (!checkObjectId.test(id)) {
return res.status(400).json({error: 'Not a user id'});
}
UserModel.findById(id, function(err, user) {
if (err) {
return console.log(err);
}
response.send(user.contacts);
});
};
exports.addContact = function(request, response) {
var id = JSON.parse(request.params.user)[0];
// validate
if (!checkObjectId.test(id)) {
return res.status(400).json({error: 'Not a user id'});
}
UserModel.findById(id, function(err, user) {
if (err) {
return console.error(err);
}
var contact = {};
// avoid to save empty info
if (request.body.first.length > 1) {contact.first = request.body.first;}
if (request.body.last.length > 1) {contact.last = request.body.last;}
if (request.body.mobile.length > 1) {contact.mobile = request.body.mobile;}
if (request.body.home.length > 1) {contact.home = request.body.home;}
if (request.body.office.length > 1) {contact.office = request.body.office;}
if (request.body.email.length > 1) {contact.email = request.body.email;}
if (request.body.company.length > 1) {contact.company = request.body.company;}
if (request.body.description.length > 1) {contact.description = request.body.description;}
if (request.body.keywords.length > 1) {contact.keywords = request.body.keywords;}
user.contacts.push(contact);
user.save(function(err) {
if (err) {
return console.error(err);
}
console.log('contact saved');
response.send(user.contacts);
});
});
};
exports.updateContact = function(request, response) {
var id = JSON.parse(request.params.user)[0];
// validate
if (!checkObjectId.test(id)) {
return res.status(400).json({error: 'Not a user id'});
}
var contact = {
_id: request.body._id,
first: request.body.first,
last: request.body.last,
mobile: request.body.mobile,
home: request.body.home,
office: request.body.office,
email: request.body.email,
company: request.body.company,
description: request.body.description,
keywords: request.body.keywords
};
UserModel.update({_id: id, "contacts._id": request.body._id}, {$set: {"contacts.$": contact}}, function(err, user) {
if (err) {
return console.error(err);
}
response.sendStatus(user);
});
};
exports.deleteContact = function(request, response) {
var id = JSON.parse(request.params.user)[0];
// validate
if (!checkObjectId.test(id)) {
return res.status(400).json({error: 'Not a user id'});
}
return UserModel.update({_id: id}, {$pull: {contacts: {_id: request.params.id}}}, function(err, user) {
if (err) {
return console.error(err);
}
console.log('contact removed');
console.log(user);
response.sendStatus(user);
});
};
It doesn't do much: fetch data from DB and return them or take data from user and save them to DB.
If it was a bit more complexe, I would surely place some logic in separate functions to reuse them and break down complexity.
Nevertheless, this code looks rather procedural, so does the hypothetical more complex version with separate functions. How would it be organized in a OOP way and how would I gain from it?
For instance, would I benefit from a User constructor?
I think the first thing you could do is nest the instance of your constructor inside an initializing function so you wouldn't have to repeat your validation code.
var connection = (function() {
var UserModel = require('../models/userModel.js');
var notAUser = {error: 'Not a user id'};
function init(request, response) {
var status = validate(JSON.parse(request.params.user)[0]);
if (!status.id) return response.status(400).json(status);
return new Connect(request, response, status.id);
}
function Connect(request, response, id) {
this.request = request;
this.response = response;
this.id = id;
this.info = { _id: id, "contacts._id": request.body._id };
}
function validate(id) {
if (!/^[0-9a-fA-F]{24}$/.test(id)) return notAUser;
else return {id: id};
}
Connect.prototype.getContact = function() {}
//etc...
return init;
})();
module.exports = connection;
Then in your actual application
var connection = require("./connection.js");
someAsync(data, function(req, res) {
var query = connection(req, res); //returned instance of constructor
query.getContact(someData, callback);
});
I would start by encapsulating the request and response since every method needs those. Like:
var contact = function (request, response) {
return {
add: add
}
function add() {
// add() gets access request and response for free
}
};
OR, if you are keen on the new operator:
function Contact(request, response) {
this.request = request;
this.response = response;
}
Contact.prototype.add = function () {
this.request;
}
Then move repeated code and callbacks to private methods you can reuse inside the object.

Categories

Resources