NodeJS MSSQL driver Passing data to a calling function - sql-server

Working with an SQL Server in NodeJS, and I have confirmed that it's pulling the data, but I'm trying to pass the data back to a calling function.
Here's my call to the function that queries the database:
const dbq = require('./dbquery.js');
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
var set = dbq.getPersonById(req.params.id);
console.log(set);
});
and here is the function inside dbquery.js:
qry.getPersonById = (id) => {
mssql.connect(sqlConfig).then(() => {
new mssql.Request().query(`select * from FNVPeople where IndivID=${id}`).then((record)=>{
console.log(record);
return record;
}).catch((err)=>{
console.log(err);
});
});
}
Should my call to the function look like this?
var dataset = await(dbq.getPersonById(req.params.id));

Because of Async nature.
Try for the following:
const dbq = require('./dbquery.js');
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
dbq.getPersonById(req.params.id, function(err, res){
console.log(res);
});
});
qry.getPersonById = (id, callback) => {
mssql.connect(sqlConfig).then(() => {
new mssql.Request().query(`select * from FNVPeople where IndivID=${id}`).then((record)=>{
console.log(record);
callback(null, record);
}).catch((err)=>{
console.log(err);
});
});
}

You should return the promise to the client to deal with (note two additional returns):
qry.getPersonById = (id) => {
return mssql.connect(sqlConfig).then(() => {
return new mssql.Request().query(`...`)
.then((record)=>{
console.log(record);
return record;
})
.catch((err)=>{
console.log(err);
});
});
}
Then, the client deals with the promise
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
dbq.getPersonById(req.params.id).then( set =>
console.log(set);
);
});
By rewriting promises to async/await you could even have
qry.getPersonById = async (id) => {
try {
await mssql.connect(sqlConfig)
var record = await new mssql.Request().query(`...`);
console.log(record);
return record;
}
catch (err) {
console.log(err);
}
}
and
app.get('/:id', async (req, res) => {
reqlog(`/${req.params.id}`);
var set = await dbq.getPersonById(req.params.id);
console.log(set);
});

Related

Fields in Mongo are not displayed

I have the following problem, after making a mongo scheme like this:
let Books = new Schema({
video_ru: String,
name: {
ru: String,
uz: String,
en: String
},
only field video_ru comes in db.
When there were no categories, everything worked as it should.
here is my Route
const express = require('express');
const booksRoutes = express.Router();
// Require books model in our routes module
let Books = require('./books.model');
// Defined store route
booksRoutes.route('/add').post(function (req, res) {
let books = new Books(req.body);
books.save()
.then(books => {
res.status(200).json({'books': 'books is added successfully'});
})
.catch(err => {
res.status(400).send("unable to save to database");
});
});
// Defined get data(index or listing) route
booksRoutes.route('/').get(function (req, res) {
Books.find(function(err, bookses){
if(err){
console.log(err);
}
else {
res.json(bookses);
}
});
});
// Defined edit route
booksRoutes.route('/edit/:id').get(function (req, res) {
let id = req.params.id;
Books.findById(id, function (err, books){
res.json(books);
});
});
// Defined update route
booksRoutes.route('/update/:id').post(function (req, res) {
Books.findById(req.params.id, function(err, books) {
if (!books)
res.status(404).send("data is not found");
else {
books.name.ru = req.body.name_ru;
books.subname.ru = req.body.subname_ru;
books.description.ru = req.body.description_ru;
books.logo.ru = req.body.logo_ru;
books.video_ru = req.body.video_ru;
books.name.uz = req.body.name_uz;
books.subname.uz = req.body.subname_uz;
books.description.uz = req.body.description_uz;
books.logo.uz = req.body.logo_uz;
books.name.en = req.body.name_en;
books.subname.en = req.body.subname_en;
books.description.en = req.body.description_en;
books.logo.en = req.body.logo_en;
books.save().then(books => {
res.json('Update complete');
})
.catch(err => {
res.status(400).send("unable to update the database");
});
}
});
});
// Defined delete | remove | destroy route
booksRoutes.route('/delete/:id').get(function (req, res) {
Books.findByIdAndRemove({_id: req.params.id}, function(err, books){
if(err) res.json(err);
else res.json('Successfully removed');
});
});
module.exports = booksRoutes;
in the end I get in the database this json
[{"_id":"5d2d94ca6206e73ff02e920d","video_ru":"","__v":0}]
but need with name fields
Well! Your schema is right. Your schema is nested so you have to save value like below or use bodyparser to wrap forms input to body.
booksRoutes.route('/add').post(function (req, res) {
let books = new Books(req.body);
books.name = {
ru: req.body.ru,
uz: req.body.ru,
en: req.body.ru
};
books.save()
.then(books => {
res.status(200).json({'books': 'books is added successfully'});
})
.catch(err => {
res.status(400).send("unable to save to database");
});
});

Firestore document not deleted

I'm trying to delete a doc from Firestore, I don't get an error but the document is still in the database: simply as that, it keeps on being in the collection it belongs to.
The cloud function is:
exports.countdowns_crud = functions.https.onRequest((request, response) => {
var req = request;
var res = response;
if (request.method === 'DELETE') {
const countdownId = request.path.split('/')[1];
const deleteOperation = db.DeleteCountdown(countdownId);
if (!deleteOperation) {
console.log('Delete operation result: ', deleteOperation);
cors(req, res, () => {
res.status(204).send("DELETED");
});
}
else {
console.error(addOperation);
cors(req, res, () => {
res.status(500).send("INTERNAL SERVER ERROR");
});
};
return;
}
cors(req, res, () => {
res.status(405).send("NOT ALLOWED");
return;
});
})
The DeleteCountdown function is in another module:
module.exports = {
DeleteCountdown: (countdownId) => {
const countdownsCollection = app.firestore.collection('countdowns');
countdownsCollection.doc(countdownId).delete()
.then((res) => {
console.log('Result: ', res);
return null;
})
.catch((e) => {
console.error(`unable to delete the countdown ${countdowmnId}: ${e}`);
return e;
});
}
}
This is the logic in a google cloud function, which it's correctly invoked by my react app upon deletion. The passed id is correct, no error is returned, but the doc keeps on living in the collection.
I had the same problem, no error and null returned (exactly the same when it works) because I forgot to set the rules to allow writes (or specifically deletions) directly in the Firebase console or by the firestore.rules files

Render template after fetching data from mongodb

app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
console.log(clientArray);
}, (err) => {
console.log("ERROR")
});
db.close();
});
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
});
Here the res.render function is being called before getting the required data from the mongodb database. I want to pass the data fetched as an array to the handlebars template.
{{#each infoArray}}
<h1>{{this.name}}</h1>
{{this.region}}
{{/each}}
Here I am trying to go through the array rendered and display the data.Any Help is appreciated.
Structure of array
[{
"name": "harshit",
"region": "delhi"
},
{
"name": "mendax",
"region": "ecuador"
}
]
Render has to be in callback function :
app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
console.log(clientArray);
db.close();
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
}, (err) => {
console.log("ERROR")
db.close();
});
});
});
You are almost there.
This is happening becuse MongoClient.connect(.. is asynchronous. So you res.render executes before that.
What you need is, just move your res.render inside that block
app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
}, (err) => {
console.log("ERROR")
});
db.close();
});
});

using two or more realtime query in one export function in firebase

Is there any way I can use two realtime database queries in one export function?
When I run this it works without errors:
exports.testDbOp = functions.https.onRequest((req, res) => {
var totalKeys = 7;
return admin.database()
.ref('/messages')
.orderByChild('id')
.startAt(2)
.limitToFirst(2)
.once('value')
.then(snap => { res.status(200).json({ total: totalKeys, date: snap.val() })
return 1
})
.catch(e => console.error(e));
});
but when I try to add the other query, it will trigger warnings on the CLI and it wouldn't show the total rows
exports.testDbOp = functions.https.onRequest((req, res) => {
var db = admin.database();
var ref = db.ref("/messages");
ref.on("value", snapshot => {
var totalKeys = snapshot.numChildren(); },
function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
return admin.database()
.ref('/messages')
.orderByChild('id')
.startAt(2)
.limitToFirst(2)
.once('value')
.then(snap => { res.status(200).json({ total: totalKeys, datas: snap.val() })
return 1
})
.catch(e => console.error(e));
});
This is what I did about, I'm trying to get the total messages key and pass it into json data but it did't work
I did it through this ugly way and it works perfectly but i still don't know where this warning in cmd is coming from around the count query
exports.testDbOp = functions.https.onRequest((req, res) => {
var returnArr = [];
var db = admin.database();
var ref = db.ref("/messages");
ref.on("value", snapshot => {
returnArr.push(snapshot.numChildren());
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
return admin.database()
.ref('/messages')
.orderByChild('id')
.startAt(2)
.limitToFirst(2)
.once('value')
.then(snap => {
res.status(200).json({ total: returnArr[0], datas: snap.val() })
return 1
}
)
.catch(e => console.error(e));
});
This is the successfully json printout
{"total":8,"datas":{"
-L8llcB9-pdbQ9eTcQa_":{"id":2,"text":"4rg","uppercase":"4RG"},"
-L8llecNccSLyULtpw5R":{"id":3,"text":"omo","uppercase":"OMO"}}}
UPADATED
I finally accomplished what i were looking for!
Here is the code for realtime firebase database pagination function with json restful api
exports.testDbOp = functions.https.onRequest((req, res) => {
var returnArr = [];
if(req.query.page){
page_number = req.query.page;}
else{
page_number = 1;}
var item_per_page = 3;
var db = admin.database();
var ref = db.ref("/messages");
ref.on("value", snapshot => {
returnArr.push(snapshot.numChildren());
});
var page_numberIncr = page_number;
var nextPosition = ++page_numberIncr;
var lastPosition = Math.ceil(returnArr[0] / item_per_page);
var position = ((page_number-1) * item_per_page);
return admin.database()
.ref('/messages')
.orderByChild('id')
.startAt(++position)
.limitToFirst(item_per_page)
.once('value')
.then(snap => {
res.status(200).json({ position: position, nextposition: nextPosition, lastposition: lastPosition, total: returnArr[0], datas: snap.val() })
return 1
}
)
.catch(e => console.error(e));
});

Chaining promises when using ES6 classes

I've the following code to upload a file to Google cloud and afterwards get the public URL. However, it quickly becomes messy when chaining the promises.
Could anyone help with a specific example of chaining the promises in a cleaner way in my example?
let routes = function(imageUploader) {
router.post('/upload',
imageUploader.getMulter().single('image'),
(req, res) => {
imageUploader.uploadFilePromise(req.file.path)
.then((filename, error) => {
if(error) throw new Error(error);
imageUploader.getExternalUrl(filename)
.then((publicUrl, error) => {
if(error) throw new Error(error);
console.log(publicUrl);
})
})
});
return router;
};
I included my ImageUploader class is here as well just as an FYI. Any other best practices suggestions are also much welcome.
const Multer = require('multer'), gcloudStorage = require('./vendors/gcloud');
class ImageUploader {
constructor() {
this.bucket = gcloudStorage;
}
uploadFile(req, res, next) {
if(!req.file) {
next();
}
this.bucket.upload(req.file.path, (err, file) => {
if(err) throw new Error(err);
req.file.publicUrl = this.getExternalUrl(req.file.name)
})
}
uploadFilePromise(path) {
return new Promise((resolve, reject) => {
this.bucket.upload(path, (err, file) => {
if(err) reject(err);
resolve(file.name);
})
})
}
getExternalUrl(filename) {
return new Promise((resolve, reject) => {
this.bucket.file(filename).getSignedUrl({
action: 'read',
expires: '03-17-2025'
}, (err, url) => {
if (err) reject(err);
resolve(url);
});
});
}
storage() {
return Multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + file.originalname)
}
});
}
getMulter() {
return require('multer')({ storage: this.storage() });
}
}
module.exports = ImageUploader;
A callback passed to then() receives one and only one argument, not two.
And it can (should) return a value, or another promise, in order to allow further chaining.
If one of the callbacks throws, or returns a rejected promise, you can handle the error with a catch at the end of the chain:
imageUploader.uploadFilePromise(req.file.path)
.then(filename => imageUploader.getExternalUrl(filename))
.then(publicUrl => console.log(publicUrl))
.catch(error -> console.log(error));
Simply regarding chaining promises with .then, I find it cleaner to not add an indent.
ex.
promise
.then(do something)
.then(do something else);

Resources