NodeJS API with Express and SQL Server database - javascript

I have a NodeJS API with Express. In my views, I need to call SQL Server functions like in the following example.
const express = require('express');
const router = express.Router();
const { poolPromise } = require('../dbconfig');
router.use(express.json());
router.post('/addDesc', async(req, res) => {
try {
const
username= req.body.nomUsager,
descr = req.body.description ;
const pool = await poolPromise;
const result = await pool.request().query(`Select dbo.AddDescr('${nomUsager}', '${descr}')`);
console.log(result.recordset[0]);
return res.json({
// I want to return the value returned by me SQL Functions, but the previous console.log() returned {"": "The function value returned"}. Is it possible to return only the value like that : { "the function value returned" }
});
} catch (err) {
return res.json({
"Fail"
});
}
});
module.exports = router
It works fine, however, how do I get only the result returned by my function rather than an object with an unnamed property? (See my console.log ())
I would like not to use an alias, all my sql function and stored procedure is done

I am not totally sure if I understand the question but you can get just the string by using:
result.recordset[0][""];.
Using the square brackets with quotes: [""] will help you get the value. However, JavaScript objects are {name: value} pairs so you cannot return a value alone.

Related

Call an imported Function in app.get(/) in nodeJS

Can I call an imported function in app.get("/")? is it good practice?
Does this also mean that all logic must be done in the addArticle function?
post.js
const addArticle = async post => {
const postData = {
body: post.body,
title: post.title,
username: post.username
};
const { data } = await axios.post(
`${BASE_URL}/data/`,
postData
);
return data;
}
catch (err) {
console.log(err)
}
index.js
const express = require('express')
const axios = require('axios')
const postfunc = require (./post.js)
const app = express()
app.get("/", post.addArticle)
app.listen(3001)
It’s acceptable to pass your route handler however you see fit. However, your addArticle function doesn’t conform to express route handler signature.
Your function should handle two arguments, being express.Request and express.Response instances respectively.
Finally, note that returning a value from a route handler does nothing — if you want to send that value to the client, you’ll need to use res.send or similar method.

Unable to export db properties from nodejs module

I am trying to export database properties stored in properties file from Javascript module. By the time I read database properties file, Javascript file is already exported and data properties appear undefined wherever I use in other modules.
const Pool = require('pg').Pool;
const fs = require('fs')
const path = require('path');
class DbConfig {
constructor(dbData) {
this.pool = new Pool({
user: dbData['user'],
host: dbData['host'],
database: dbData['database'],
password: dbData['password'],
max: 20,
port: 5432
});
}
}
function getdbconf() {
const dbData = {};
fs.readFile("../../db_properties.txt"), 'utf8', (err, data) => {
if (err) {
console.error(err)
return
}
// dbData = {"user":"postgres", "password": "1234"...};
return dbData;
});
}
let db = new DbConfig(getdbconf());
let dbPool = db.pool;
console.log("dbpool : -> : ",dbPool); // username and password appear undefined
module.exports = { dbPool };
Is there a way to read data before exporting data from Javascript module?
Usually database config or any other sensitive info is read from a .env file using dotenv .
Or
you could also provide env from command line itself like
DB_HOST=127.0.0.1 node index.js
inside your index.js
console.log(process.env.DB_HOST)
Please create a new file (connection-pool.js) and paste this code:
const { Pool } = require('pg');
const poolConnection = new Pool({
user: 'postgresUserName',
host: 'yourHost',
database: 'someNameDataBase',
password: 'postgresUserPassword',
port: 5432,
});
console.log('connectionOptions', poolConnection.options);
module.exports = poolConnection;
For use it, create a new file (demo-connection.js) and paste this code:
const pool = require('./connection-pool');
pool.query('SELECT NOW();', (err, res) => {
if (err) {
// throw err;
console.log('connection error');
return;
}
if (res) {
console.log(res.rows);
pool.end();
}
});
This is an alternative option 🙂
Exporting the result of async calls
To export values which have been obtained asynchronously, export a Promise.
const fs = require('fs/promises'); // `/promise` means no callbacks, Promise returned
const dbDataPromise = fs.readFile('fileToRead')); //`readFile` returns Promise now
module.exports = dbDataPromise;
Importing
When you need to use the value,
const dbDataPromise = require('./dbdata');
async init() {
const dbData = await dbDataPromise;
}
//or without async, using Promise callbacks
init() {
dbDataPromise
.then(dbData => the rest of your code that depends on dbData here);
}
Current code broken
Please note that your current code, as pasted above, is broken:
function getdbconf() {
const dbData = {};
fs.readFile("../../db_properties.txt"), 'utf8', (err, data) => {
//[...] snipped for brevity
return dbData;
});
}
fs.readFile "returns" dbData, but there is nothing to return to, since you are in a callback which you did not call yourself. Function getdbconf returns nothing.
The line that says let db = new DbConfig(getdbconf()); will NOT work. It needs to be inside the callback.
The only way to avoid putting all of your code inside the callback (and "flatten" it) is to use await, or to use readFileSync
Avoiding the issue
Using environment variables
Suhas Nama's suggestion is a good one, and is common practice. Try putting the values you need in environment variables.
Using synchronous readFile
While using synchronous calls does block the event loop, it's ok to do during initialization, before your app is up and running.
This avoids the problem of having everything in a callback or having to export Promises, and is often the best solution.

Can't synchronise mongoose operation to return an array

As a part of an employee's app management, I want to separate the business logic database operations from my main application file.
The simplest operation is to read all the employees from the database using async/await to synchronize it:
module.exports.getEmployees = async () => {
const employees = await Employee.find();
return employees;
}
in my app.js I typed the following code:
const employee = require(__dirname + "/models/employee.js");
app.get("/employees", (req, res) => {
const employeeList = employee.getEmployees();
employeeList.then(res.send(employeeList));
})
but still, the array shows up empty?
then clause in promise accepts a functions as an argument & this function has a parameter which holds the actual response.
Something like this -
new Promise().then((response) => {
console.log(response);
});
You are doing employeeList.then(res.send(employeeList)); which means the argument to then clause is res.send() which won't work.
Try this -
employeeList.then((list) => {
// please note the response type here depends on the Content-Type set in the response Header
res.send(list);
// In case of normal http server, try this -
res.send(JSON.stringify(list));
});
I hope this helps.

how to retrieve and pass data from more than 1 Schema in a function

im newbie in expressjs and wondering how to retrieve and pass data from more than 1 schema in my controller.
here is the case, pretend i wanna open add_new_blog page and below is
the router;
router.get('/add_new_blog', BlogController.index);
well then in BlogController.index i need to retrieve Category and Tag Models.
const Category = require('models/categorySchema');
const Tag = require('models/tagSchema');
module.exports = {
index(req, res, next){
Category.find({});
Tag.find({});
// how to find/retrieve data from both Schema then i pass them to Views.
res.render('/blog/blogForm');
}
}
The Question is What the coding will look like to retrieve the data from both then pass it to the view?
You can use Promise.all(), get the two mongoose calls data and then render it.
const categoryFind = Category.find({}).exec(); // exec() returns a Promise.
const tagsFind = Tags.find({}).exec();
Promise.all(categoryFind, tagsFind).then((values) => {
res.render('/blog/blogForm', { categories: values[0], tags: values[1] });
});
Notice that I render inside the callback, that is because mongoose calls are asynchronous. Otherwise you will be rendering before the queries have completed.
That is the same as:
Category.find({}, (err, catData) => {
Tags.find({}, (err, tagsData) => {
res.render('/blog/blogForm', { categories: catsData, tags: tagsData });
}
}

How does this callback call work in Node.js with mongo .find call

models/category.js
var mongoose = require('mongoose');
// Category Schema
var categorySchema = mongoose.Schema({
title: {
type: String
},
description: {
type: String
},
created_at: {
type: Date,
default: Date.now
}
});
var Category = module.exports = mongoose.model('Category', categorySchema);
// Get Categories
module.exports.getCategories = function(callback, limit) {
Category.find(callback).limit(limit).sort([['title', 'ascending']]);
}
routes/categories.js
var express = require('express');
var router = express.Router();
Category = require('../models/category.js');
router.get('/', function(req, res, next) {
Category.getCategories(function(err, categories) {
if (err) res.send(err);
res.render('categories',
{
title: 'Categories',
categories: categories
});
});
});
router.post('/add', function(req,res) {
res.send('Form Submitted');
});
module.exports = router;
I got a few questions about this code
a) how does the callback mechanism work from routes/categories.js when we pass that callback function to models/category.js in Category.find(callback). That seems bizarre to me since we are doing a whole res.render which becomes part of Category.find() ?
b) Where is limit specified?
c) Why isn't there var in front of Category = require('../models/category.js');
a) that is indeed what happens, and is good: res.render will not get called until the find() operation executes on the database and a result is sent back for the mongoose code to return to you. You want to run the callback function after you get the result for your query, and so calling res.render before would be much more bizarre.
b) in the documentation. http://mongoosejs.com/docs/api.html#model_Model.find yields a Query object, which may be synchronously (i.e. before the query is actually made to resolve at the database) further specified with where, limit, etc.
c) because someone got lazy. In this example it doesn't actually make a difference because without var (or const or let in modern JS) a variable declaration is tacked onto the local context, which in your file is the routes/categories.js module context, and because Categories is declared at the top of that scope, var doesn't change where the variable ends up being bound. But it's lazy, and for good example code, that should have var in front of it.

Categories

Resources