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

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.

Related

Why is my code error not stopping the function in nodejs?

My self and another developer are working on an API using node.js and we are not advanced coders yet. We ran into problem. I will try and explain the problem here with sample references.
We have an API route that would be called on the frontend, please this is just a sample and not the real code. client said the codes should be private. We want to stop the function when an error is detected in another function we called. I am sure that we are not doing it rightly. Here is the API route for this post request and we called another function that we exported and imported here.
We simply want the httpCreateHarsh function to end if there is an error in the anotherFunction. With what we have, the error is seen in console.log when the user is not an admin for example but the httpCreateHarshfunction keeps running until it reaches the last line. Is this possible? Or is there another way we can structure the code to achieve this?
Shared sample of my code
const callAnotherFunction = require("../anotherfunction")
const httpCreateHarsh = async(req, res) => {
await callAnotherFunction(req, res);
return res.status(200).json('created')
}
//This is the second function we called:
const obj = {
status: 'success',
code: '244'
}
const anotherFunction = async(req, res) => {
if (req.body.user !== 'admin') {
return res.status(401).json('Unauthorized')
}
return obj
}
export default = anotherFunction
//The route here:
const express = require('express');
const router = express.Router();
const httpCreateHarsh = require('../httpCreateHarsh');
router.post("/harsh", httpCreateHarsh)
You couldn't return the res object in your second function.
To solve this problem you could throw exceptions and catch them in your handler function.
// request handler function
const httpCreateHarsh = async (req, res) => {
try {
await callAnotherFunction(req, res);
} catch (e) {
return res.status(401).json('Unauthorized')
}
return res.status(200).json('created')
}
const anotherFunction = asyn(req, res) => {
if (req.body.user !== 'admin') {
throw new Error('Unauthorized')
}
return obj
}
What you can do is you can wrap the code in httpCreateHarsh in an try...catch so whenever there is error inside it it will trigger the catch block and u exit the api.
const httpCreateHarsh = async(req, res)=>{
try{
await callAnotherFunction(req, res);
return res.status(200).json('created')
} catch(err){
return res.status(401).json('Unauthorized')
}
}
As an addition to this code you can return a promise from anotherFunction so that the catch block will be triggered once the promise is rejected.
For Exmaple:
const anotherFunction = async(req, res) => {
return new Promise(function(myResolve, myReject) {
if (req.body.user !== 'admin') {
myReject();
}
myResolve(obj);
});
}
If the code runs as you want it, it will generate the "cannot set headers after they are sent to the client" error, because you will be returning 2 responses
the first will be "unauthorized" by "anotherFunction" function and then the other response which is "created" of the current function "httpCreateHarsh".
what you should do instead is to call the "anotherFunction" as a middleware before moving to the "httpCreateHarsh" function.
it can be done this way:
// anotherfunction.js file containing the function you want to import
module.exports = {
async anotherFunction(req, res) {
if (req.body.user !== 'admin') {
return res.status(401).json('Unauthorized')
}
// this way, you can access this object from the "httpCreateHarsh" function by using req.body.obj
req.body.obj = {
status: 'success',
code: '244'
}
// this next indicates that there were no errors, and the next function will be called
next();
}
}
const httpCreateHarsh = async(req, res) => {
// do wathever you want here
return res.status(200).json('created')
}
//The route here:
const express = require('express');
const router = express.Router();
const httpCreateHarsh = require('../httpCreateHarsh');
const callAnotherFunction = require("../anotherfunction")
router.post("/harsh", (req, res, next) => callAnotherFunction(req, res, next), httpCreateHarsh)

Next.js API functions run multiple times on one call

I am using a Next.js API call to retrieve some data from an external API (I know this is better done with getStaticProps but I need to make a few calls before passing the data to the client.)
I don't understand why doe the backend function runs multiple times, and on the first time it doesn't have the POST data.
cleint
export default function Customer () {
const router = useRouter()
const { id: submissionId } = router.query
const { data: customer, error } = useSWR(['/api/jotform/get-client/', submissionId], fetcher)
...
server
export default async function handler (req, res) {
try {
const customers = await axios.get('https://api.jotform.com/form/' + jotformAPI.form_id + '/submissions?apiKey=' + jotformAPI.key)
const { submissionId } = req.body
const customer = customers.data.content.find(client => client.id === submissionId)
if (!customer) throw new Error('contact does not exist')
//on the first call the error is triggered, only on the second time I get the data.
...

Why is this catch all API route not working?

SO I been learning NextJS API routes and NodeJS recently, While I do know how to create dynamic routes now, I have some issues with a few things -
This is my api/matches.js file.
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default async function handler(req, res) {
const response = await fetch(`https://exampleapi.com/?&token=# `)
const jsonData = await response.json();
res.status(200).json(jsonData);
}
Now, I have another dynamic route for this API which fetches the match by a match slug, So this file was called /api/matches/[...matchslug].js
export default async function handler(req, res) {
const page = req.query.matchslug
const response = await fetch(`https://examleapi.com/?search[slug]=${page}&token=# `)
const jsonData = await response.json();
While this dynamic route fetches the result of one so if I went matches/exampelmatch, I do get the results for the examplematch, However I'm looking to somehow implement it in a way that
matches/examplematch1/examplematch2
Returns the data from the examplematch1 & examplematch2.
I'm not sure if building something like is possible, But very interested.
Thank you for your time and patience.
In your /api/matches/[...matchslug].js example, the value of matchslug will always be an array.
Instead of passing the page variable directly into fetch, you can map over the values in the matchslug array and use Promise.all to request each resource.
It would look something like this (I haven't tested this):
export default async function handler(req, res) {
const promiseArray = req.query.matchslug.map(async (slug) => {
const response = await fetch(`https://examleapi.com/?search[slug]=${slug}&token=# `)
const jsonData = await response.json();
return jsonData
})
const result = await Promise.all(promiseArray)
res.status(200).json(result);
}

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.

NodeJS API with Express and SQL Server database

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.

Categories

Resources