How to display result from async function in Node.js - javascript

I'm new in Node and I've watched some of the tutorials from the Net.
My main problem is how I can show the result from the route I created. Well, I'm getting the correct data using the console but when I access it through browser it doesn't show the json encoded data.
Here is my product.js:
const express = require('express');
const router = express.Router();
const connection = require('../connection');
router.get('/',(req,res)=>{
res.send(products());
})
async function products(){
// console.log(products)
return await getProducts();
}
function getProducts(){
return new Promise((resolve,reject) =>{
connection.query('SELECT brand,description from products limit 100', function (err, rows, fields) {
if (err) throw err
resolve(JSON.stringify(rows))
})
})
}
module.exports = router;
Here is the console log result : http://prntscr.com/llxgk2
Here is the result from the postman: http://prntscr.com/llxgy3

You need to consume the promise. In your case, probably with then and catch handlers:
router.get('/',(req,res)=>{
products()
.then(products => {
res.json(products);
})
.catch(error => {
// ...send error response...
});
});
Note I've used res.json to send the response. You probably want to change your resolve(JSON.stringify(rows)) to just resolve(rows) and leave what to do with the rows to the caller. (res.json will stringify for you.)
You might also look at Koa, which is from the same people who did Express, which provides first-class support for async functions as routes.

Related

How to return the results of mySql query using express.js?

I am trying to get the results of my simple SELECT command to the index.js file, where I would like to have all records separated in a array. If I print the results in the database.js the JSON.parse just work fine. But if I want to return them and get them into the index.js where I need them, I always get undefined when I print it.
index.js CODE
const express = require('express');
const app = express();
const database = require('./database');
app.use(express.json());
app.use(express.urlencoded());
app.use(express.static('public'));
app.get('/form', (req,res) =>{
res.sendFile(__dirname + '/public/index.html' );
console.log(req.url);
console.log(req.path);
})
app.listen(4000, () =>{
console.log("Server listening on port 4000");
database.connection;
database.connected();
//console.log(database.select());
let results = [];
//results.push(database.select('username, password'));
let allPlayer = database.select('username');
console.log(allPlayer);
});
database.js CODE
let mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
database: 'minigames',
user: 'root',
password: 'root'
});
function connected(){
connection.connect((err) => {
if(err) throw err;
console.log("Connected...");
})
}
function select(attribute){
let allPlayer = [];
let sql = `SELECT ${attribute} FROM player`;
let query = connection.query(sql, (err, result, field) => {
if(err) throw err;
return Object.values(JSON.parse(JSON.stringify(result)));
})
}
module.exports = {connection, connected, select};
Understand that one of the main things that make JavaScript different from other languages is that it's asynchronous, in simple terms meaning code doesn't "wait" for the code before it to finish executing. Because of this, when you're trying to query a database, which takes some time, the code after it gets impatient and executes regardless of how to the query is doing. To solve this problem, the mysql package utilizes callbacks, which allows you to pass a function to it to execute once the query is finished with the queries result.
Because the library operates on callbacks, it doesn't return anything; that seems quite problematic for using it somewhere else, doesn't it?
To solve this problem, we can make our own callback. Or better yet, use the newer JavaScript feature called promises, where you can basically "return" anything from a function, even when you're in a callback.
Let's implement it with the query:
function select(attribute) {
return new Promise((resolve, reject) => {
let sql = `SELECT ${attribute} FROM player`;
let query = connection.query(sql, (err, result, field) => {
if(err) return reject(err);
resolve(Object.values(JSON.parse(JSON.stringify(result))));
});
});
}
To "return" from a promise, we pass a value to the resolve function. To throw an error, we call the reject function with the error as the argument.
Our new function is rather easy to use.
select("abcd").then(result => {
console.log("Result received:", result);
}).catch(err => {
console.error("Oops...", err);
});
You might look at this code and go, "Wait a minute, we're still using callbacks. This doesn't solve my problem!"
Introducing async/await, a feature to let you work just with that. We can call the function instead like this:
// all 'await's must be wrapped in an 'async' function
async function query() {
const result = await select("abcd"); // woah, this new await keyword makes life so much easier!
console.log("Result received:", result);
}
query(); // yay!!
To implement error catching, you can wrap you stuff inside a try {...} catch {...} block.

res.redirect causes error in .catch statement

I am using Node.js and have a database call being performed with a promise. I setup a '.then/.catch' to handle the result of the promise. That part all seems to work without any issue. After I do some processing of the data returned from the database I am attempting to 'redirect' to another route within the '.then' statement. This re-direction seems to be causing a problem with the '.catch' statement. I have no error issues if I remove the 'res.redirect'...is there a workaround? Any suggestions appreciated.
code:
const db = require('./routes/queries');
//**Query PostGres database...
db.getMembers()
.then(function(value) {
console.log('Async success!', value);
//do some processing on the data returned from the promise call here...
//if I insert a redirect here...such as "res.redirect('/_members');"...
//I get a "Caught an error! ReferenceError: res is not defined" message...?
//evidently the redirect fires the '.catch' statement below...why?
})
.catch(function(err) {
console.log('Caught an error!', err);
});
I recommend providing a reusable promise in case you need to find your members list elsewhere in your Express app
const db = require('./routes/queries');
const findMembers = () => {
return db.getMembers()
.then(members => {
return members
})
.catch(err => {
console.log('Caught an error!', err);
});
}
//inside your express app
app.get("/some_route", (req, res) => {
return findMembers()
.then(members => {
//do something with your members list
res.redirect("/redirect_route")
})
})

Why is catch() block not running in Objection.js queries and instead then() always runs passing either 0 or 1 as a result?

So when running a query using Objection.js, the query will return data based on success or failure of said query and this data is passed to the then() block as a 0 or 1. Meaning to error handle, I'm having to check falsey values rather than send a response in the catch block. Am I doing something wrong?
const editIndustry = async (req, res, next) => {
const industry = await Industry.query().findById(req.params.industryId);
if (!industry) {
return res.status(404).json({
error: 'NotFoundError',
message: `industry not found`,
});
}
await industry
.$query()
.patch({ ...req.body })
.then(result => console.log(result, 'then() block'))
// never runs
.catch(err => {
console.log(err);
next(err);
});
};
App is listening on port 3000.
1 then() block ran
Your code is working as expected. The reason it's not going into the catch block is because there isn't an error. patch does not return the row. It returns the number of rows changed (see docs).
The function I think you're really looking for is patchAndFetchById (see docs). If you're concerned about generating a 404 error, you can append throwIfNotFound. Obviously, this will throw if it's not found in the database, which will let you catch. You can catch an instance of this error so you can send a proper 404 response. Otherwise, you want to return a 500. You'd need to require NotFoundError from objection.
const { NotFoundError } = require('objection');
const Industry = require('<myIndustryModelLocation>');
const editIndustry = (req, res) => {
try {
return Industry
.query()
.patchAndFetchById(req.params.industryId, { ...req.body })
.throwIfNotFound();
} catch (err) {
if(err instanceof NotFoundError) {
return res.status(404).json({
error: 'NotFoundError',
message: `industry not found`,
});
}
return res.status(500);
}
};

Node express: not able to access data after query execution

I have a simple custom module in which all methods are supposed to return database records.
I am getting all records after running a query but when I try to assign those records to some variable then it says null. Not sure what is going on.
Here is my custom module code:
module.exports = {
mydata: {},
all: function (req, res, next) {
var posts = null;
con.query("SELECT post_id,title, body from `posts`", function (err, rows, fileds) {
if (err) {
console.log('Error' + err);
}
posts = rows[0]; // assigned object object to posts but not working
console.log('names' + posts);
});
console.log('my posts' + posts); // it says null/empty
return posts; // empty return
},
I am calling all methods like this in my route:
console.log("admin.js :" + postModel.all());
All are empty or null. Please guide or suggest. Am I missing anything?
Try using async & await plus it's best practice to wrap the code in try catch, any pending promise will be resolved at the .then method or any error will be caught at the .catch of the caller/final function:
/ * Handler (or) Service (or) Whatever */
const FetchDataFromDB = require('../');
/* caller Function */
let fetchDataFromDB = new FetchDataFromDB();
fetchDataFromDB.getDataFromDB()
.then((res) => console.log(res))
.catch((err) => console.log(err))
/* DB Layer */
class FetchDataFromDB {
/* Method to get data from DB */
async getDataFromDB() {
const getQuery = "SELECT post_id,title, body from `posts`";
try {
let dbResp = await con.query(getQuery);
if (dbResp.length) {
//Do some logic on dbResp
}
return dbResp;
} catch (error) {
throw (error);
}
}
}
module.exports = FetchDataFromDB;
Welcome my friend to the world of Asynchronous function.
In your code the
console.log('my posts' + posts); and return posts;
are executing before the callback assigns values to the posts variable.
Also restrict yourself from using var instead use let for declaring variable works better without error for scoped functions.
Here below:
The async keyword declares that the function is asynchronous.
The await keyword basically says that lets first get the result and then move on to next statement/line. All awaits should be done inside an async functions only.
module.exports = {
mydata: {},
all: async function (req, res, next) { //Let this be an asynchronous function
try{
let [rows, fields] = await con.query("SELECT post_id,title, body from `posts`");
//let us await for the query result so stay here until there is result
let posts = rows[0]; // assign first value of row to posts variable now
console.log('my posts' + posts);
return posts;
}catch(err){
return err;
}
},
}
Please take time reading up nature of Asynchronous, Non-blocking in JavaScript and how to handle them with Promises or Async/await (my personal choice).

From where should I call module.exports to get a not null value?

Where should I call module.export, I assume, it's supposed to be a callback function.
But I'm confused as to where am I supposed to call the callback function.
I'm still confused with the solution, too complicated for me.
sql.connect(config, function(err) {
if (err)
console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select part_num,qty from CRM.CRM.Fishbowl_Inventory where not location = \'Shipping\'',
function(err, recordset) {
if (err)
console.log(err)
// send records as a response
var details = recordset;
});
});
module.exports = details;
Confusion:
Extremely sorry to bother you guys but I want to be sure that I'm doing no harm to our database by involving any database request through Javascript.
I'm testing directly with our production database, hence cautious
So as Max provided in his answer the following code
const connectToSql = require('./connectToSql');
connectToSql()
.then(details => {
console.log(details);
//Here I can do as much logic as I want
//And it won't affect my database or call multiple requests on my DB
})
.catch(err => {
console.log(err);
});
I can understand I'm asking super silly questions, very sorry about that.
You can't export the result of your function. You want to export a function that will return your value. Like this:
function connectToSql(config) {
return new Promise((resolve, reject) => {
sql.connect(config, function (err) {
if (err) {
console.log(err);
reject(err);
}
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select part_num,qty from CRM.CRM.Fishbowl_Inventory where not location = \'Shipping\'',
function (requestErr, recordset) {
if (err) {
console.log(requestErr);
reject(requestErr);
}
resolve(recordset);
});
});
});
}
module.exports = connectToSql;
Because your function is async, I returned a promise that will return your result. Also, your second error from your query is named the same as your first error from the connection. That would cause problems.
Example of how to use this:
const connectToSql = require('./connectToSql');
connectToSql()
.then(details => {
console.log(details);
})
.catch(err => {
console.log(err);
});

Categories

Resources