Node.js npm mssql function returning undefined - javascript

I am using mssql with node.js to connect to an sql server db. I am trying to reduce code by wrapping the connection code in a function with one query parameter. When I call the function from with in a router.get function, it returns undefined.
Any help would be much appreciated.
function sqlCall(query) {
var connection = new sql.Connection(config, function(err) {
if (err) {
console.log("error1");
return;
}
var request = new sql.Request(connection); // or: var request = connection.request();
request.query(query, function(err, recordset) {
if (err) {
console.log("error2");
return;
}
return (recordset);
});
});
}
router code
router.get('/', function(req, res) {
var queryString = "select * from .....";
res.json(sqlCall(queryString));
//sqlCall(queryString)
});

You are trying to treat the sqlCall as a synchronous function with a return value, while the request.query function on the opposite is an asynchronous function, expecting a callback.
Since Node.js uses non blocking IO and callback structures for flow control, using an asynchronous structure based around callbacks is the way to go. In your case this could look like this:
router.get('/', function(req, res) {
var queryString = "selec * from .....";
sqlCall(queryString, function(err, data) {
if (typeof err !== "undefined" && err !== null) {
res.status(500).send({
error: err
});
return;
}
res.json(data);
});
});
with your other component looking like this:
function sqlCall(query, cb) {
var connection = new sql.Connection(config, function(err) {
if (typeof err !== "undefined" && err !== null) {
cb( err );
return
}
var request = new sql.Request(connection); // or: var request = connection.request();
request.query(query, function(err, recordset) {
cb( err, recordset );
});
});
}

Related

how to return response to REST api in node js

I'm new to Node JS. My node js REST api route code is:
'use strict';
module.exports = function(app) {
var sequel = require('../controllers/sampleController');
app.get('/task?:email', function(req, res){
res.send(sequel.listByEmail(req.query.email));
});
};
And my listByEmail function is:
'use strict';
var apiKey = '1xxxxxxxxL';
exports.listByEmail = function(emailid) {
console.log(emailid);
if(emailid != null && emailid != undefined) {
var xyz = require("xyz-api")(apiKey);
xyz.person.findByEmail(emailid, function(err, data) {
if(data.status == 200){
return data; // data is in json format
}
});
}
};
I returned data like this from that listbyemail function. Data is there, if i try to print the data in console it appears. But while returning the data, it won't returned. It's always return undefined. I can't able to catch the result data from listByEmail function in route and not able to send it as response. Please helpMe!!!
In your ListByEmail function you are calling an asynchronous method, findByEmail.
When you reach the return data; line, your listByEmail function already returned so you are not returning anything to the caller.
You need to handle it asynchronously, for example:
'use strict';
var apiKey = '1xxxxxxxxL';
exports.listByEmail = function(emailid) {
return new Promise(function(resolve, reject) {
console.log(emailid);
if(emailid != null && emailid != undefined) {
var xyz = require("xyz-api")(apiKey);
xyz.person.findByEmail(emailid, function(err, data) {
if(data.status == 200){
resolve(data); // data is in json format
}
});
} else {
reject("Invalid input");
}
};
Then:
'use strict';
module.exports = function(app) {
var sequel = require('../controllers/sampleController');
app.get('/task?:email', function(req, res){
sequel.listByEmail(req.query.email).then(function(data) {
res.send(data);
});
});
};
This is a very basic example of using Promise to handle asynchronous calls in node. You should study a little bit how this works. You can start for example by reading this: https://www.promisejs.org/
UPD Once you understand how to deal with callbacks, you'd better to look towards Promises, async/await, and async.js
Your function #findByEmail is asynchronous, so possibly your route should look like
'use strict';
module.exports = function(app) {
var sequel = require('../controllers/sampleController');
app.get('/task?:email', function(req, res){
sequel.listByEmail(req.query.email, function(err, list){
if(err){
console.error(err);
//handle error
}
res.send(list);
})
});
};
and your #listByEmail function should be like
'use strict';
var apiKey = '1xxxxxxxxL';
exports.listByEmail = function(emailid, callback) {
console.log(emailid);
if(emailid != null && emailid != undefined) {
var xyz = require("xyz-api")(apiKey);
xyz.person.findByEmail(emailid, function(err, data) {
if(err){
callback(err);
} else if(data.status == 200){
callback(null, data);
}
});
}
};

Node.js: Async fs.writeFile queue is creating race condition?

I am trying to use async with node.js to handle multiple incoming POST requests to edit a JSON file. No matter how I refactor it, it will always make one of the edits and not the other. I though that using async.queue would force the operations to handle sequentially? What am I doing wrong?
My code:
var editHandler = function(task, done) {
var req = task.req;
var res = task.res;
fs.stat( "./app//public/json/" + "data.json", function(err, stat) {
if(err == null) {
console.log('File exists');
} else if(err.code == 'ENOENT') {
console.log("Error");
} else {
console.log('Some other error: ', err.code);
}
});
console.log(req.params.id);
console.log(req.body);
fs.readFile( "./app//public/json/" + "data.json", 'utf8', function (err, data) {
data = JSON.parse( data );
data[req.params.id] = req.body.school;
//console.log( data );
fs.writeFile("./app//public/json/" + "data.json", JSON.stringify(data), function (err){
if(err) {
return console.log(err);
}
})
res.redirect('/');
});
};
//Make a queue for the services
var serviceQ = async.queue(editHandler, 20);
serviceQ.drain = function() {
console.log('all services have been processed');
}
app.post('/edit_school/:id', function(req, res) {
serviceQ.push({req: req, res: res })
})
Thanks in advance for any insights! I am really new to using node.js for anything other than npm/webpack.

NodeJS wait until mySQL query is completed

I trying to pass a object from the controller to the view. Because I want to my model separate my query's from the controller I'm loading a JS object (model).
My model looks as follows:
function MyDatabase(req) {
this._request = req;
this._connection = null;
this.init();
};
MyDatabase.prototype = {
init: function() {
this._request.getConnection( function(err, con) {
if(err) return false;
return this._connection = con;
}.bind(this));
},
getFromTable: function(table) {
this._connection.query('SELECT * FROM '+ table +';', function(err, result) {
if(err)
return false;
else if( !result )
return {error: 'Error bij het ophalen van foto\'s'};
else
return result;
}.bind(this));
}
};
module.exports = MyDatabase;
But I can't figure out how to wait until this query is completed in my controller. I've found the async module and tried multiple function like waterfall and parallel, but none of them worked for me (or I didn't use it as supposed to).
My controller currently looks as seen below:
var myDatabase = require('../dbmodel');
router.get('/', function(req, res, next) {
var db = new myDatabase(req);
async.waterfall([
function(callback) {
var db = new myDatabase(req);
var photos = db.getFromTable('photos');
callback(null, photos);
}
], function(p) {
res.locals.photos = p;
res.render('photos');
} );
});
What am I doing wrong? I do understand that NodeJS works async and doesn't wait for any function to be completed. But there must be a way this is possible. What am I doing wrong, or what do I misunderstand?
Thanks in advanced! ;)
The getFromTable method should accept a callback that will process the result of its execution.
// Accept a callback as a parameter
getFromTable: function(table, callback) {
this._connection.query('SELECT * FROM '+ table +';', function(err, result) {
if(err)
// execute the callback for a null result and an error.
callback(err, null);
else if( !result )
callback(new Error('Error bij het ophalen van foto\'s'),null);
else
// execute the callback on the result
callback(null, result);
}.bind(this));
}
The method can now be used in this manner:
// This is the callback to be passed into the method.
function processResult(err, result) {
console.log(result);
}
db.getFromTable('photos', processResult);

creating a dynamically restful api for node.js

I'm using mongodb for pretty much everything in my node.js application, and now i want create a restful application, so, i did that:
I'm trying to do just the get method, for now:
restApi.js:
var restAPI = {
get: function(method, model, sort, limit, options) {
if (method !== 'get') {
return;
}
model.find(options).sort(sort).limit(3).exec(function (error, result) {
if (error) {
return error;
} else {
return result;
}
});
},
};
And now i can require this in my route:
var restApi = require('restApi');
and use like this:
app.get('/', function(req, res, next) {
var result = restAPI.get('get', Event, 'date', 3, {'isActive': true});
res.render('/', {
result: result
});
});
Is not working, the result is undefined. Why??
How can i transform this in a async function with callback? This is possible?
Thanks! :)
You're not returning anything from restApi.get. If you're using mongoose, you could return a Promise easily enough:
var restAPI = {
get: function(method, model, sort, limit, options) {
if (method !== 'get') {
return;
}
return model.find(options).sort(sort).limit(3).exec();
},
};
Then you can use it like this:
app.get('/', function(req, res, next) {
restAPI.get('get', Event, 'date', 3, {'isActive': true}).then( function ( result ) {
res.render('/', {
result: result
});
}).catch( error ) {
// Render error page and log error
});
});
It is because your model is async. You have to pass callbacks.
Using async way is better because it is not blocking your application while waiting for response.
Example on your case:
restApi.js:
var restAPI = {
get: function(method, model, sort, limit, options, cb) {
if (method !== 'get') {
return cb("Method must be GET");
}
model.find(options).sort(sort).limit(3).exec(function (error, result) {
if (error) {
return cb(error);
} else {
return cb(null, result);
}
});
},
};
And now i can require this in my route:
var restApi = require('restApi');
and use like this:
app.get('/', function(req, res, next) {
restAPI.get('get', Event, 'date', 3, {'isActive': true}, function(err, result){
if(err)
return res.render("Error:" + err)
res.render('/', {
result: result
});
});
});
I've added cb argument to your REST API function so it is called when model async operation is done.
Router handler passes it's callback and prints output when operation is finished.

expressJS : separating route, model, making exported properties from model to route to work async?

Im new to js/nodejs/express, and on my own tried to structure my file in an MVC like pattern
The problem is the console.log (at routes.js, the most important) returns undefined, while the second one returns the real data, and is executed by node respectively as well, How would I return that data in an async manner from my model to the route?
In my server.js
require('./modules/pos/routes')(app);
require('./modules/pos/models/inventory')(app);
In my routes.js
module.exports = function(app) {
Inventory = require('./models/inventory')(app);
app.get('/poss', function(req, res) {
var result = Inventory.get();
console.log('result1 is',result); // !
res.end(JSON.stringify(result));
});
}
In my inventory.js
module.exports = function(app) {
return {
get : function() {
var res;
app.conn.query('SELECT * FROM users', function(err, rows) {
res = JSON.stringify({users : rows});
console.log("result is ",res); // !
return res;
});
}
}
}
P.S executing node server in the terminal, and browsing to localhost:8000 gives
result1 is undefined
result is {"users":[{"id":1, "username": ...blah..
Your first console.log is executed before the second. And the get method doesn't return anything because the method that returns is the one inside the get. In order to make your method async add a callback, like this:
// inventory.js
module.exports = function(app) {
return {
get : function(cb) {
app.conn.query('SELECT * FROM users', function(err, rows){
if (err) {
return cb(err);
}
res = JSON.stringify({users : rows});
console.log("result is ", res);
cb(null, res)
});
}
};
};
// routes.js
module.exports = function(app) {
var Inventory = require('./models/inventory')(app);
app.get('/poss', function(req, res) {
Inventory.get(function (err, result) {
if (err) {
// do something else in case of error
return;
}
res.end(result); // you don't need to use json stringify here cause the result is serialized
});
});
}

Categories

Resources