I'm looking at separating out my mongo db queries into a separate js file to help with reusing the code, something in the format below (this doesn't work). Any ideas how I could do this?
queries.js
var Merchants = require('../models/Merchants');
var query = {
returnMerchantIDs: function () {
var results = Merchants.find(function(err, merchants){
if (err) return console.error(err);
return merchants;
})
return results;
}
module.exports = query;
routes.js
var queries = require('../config/queries');
app.get('/queries', function (req, res) {
res.send(queries.returnMerchantIDs());
});
Your 'return merchants' is actually returning from the callback and not from the returnMerchantIDs function. That is the reason this is not working. There are 2 ways you could go about doing this.
Have returnMerchantIDs accept a callback like so
var query = {
returnMerchantIDs: function (callback) {
var results = Merchants.find(function(err, merchants){
if (err) return console.error(err);
callback(merchants);
})
return results;
}
and this is how you would call this
app.get('/queries', function (req, res) {
queries.returnMerchantIDs(function(merchants) {
res.send(merchants);
}));
});
Or return the promise from mongoose to the caller and exec there passing the callback
var query = {
returnMerchantIDs: function () {
var results = Merchants.find();
return results;
}
}
app.get('/queries', function (req, res) {
queries.returnMerchantIDs().exec(function(err, merchants)) {
if (err) res.send(err) else res.send(merchants);
}
Related
I am using nodeJs Express and I have an async function which is used in another function.
here is my code:
/* get user info */
const getUserInfo = async (req) => {
let userID = req.cookies.userId;
if(!userID) return null;
await connection.query('SELECT * FROM users WHERE id = ' + userID,
function (err, rows, fields) {
if (err) throw err
// if user not found
if (rows.length === 0) {
return null;
}
// if user found
else {
return rows[0];
}
});
}
/* display dashboard page */
router.get("/", async function (req, res, next) {
let userInfo = await getUserInfo(req);
console.log(userInfo) // It's result is undefined
if (userInfo) {
res.render('dashboard/profile', {
fullName: userInfo.fname + " " + userInfo.lname,
email: userInfo.email,
phone: userInfo.phone,
});
}
else {
res.render('authentication/register', {
title: 'ثبت نام',
});
}
});
how to resolve this problem? I need userInfo retun me some data.
await is only useful if the value on the right-hand side is a promise.
connection.query is taking a callback function, which implies it isn't returning a promise.
You need to either:
Find out how to make the API you are using return a promise (if that is possible)
Wrap the callback in a promise
Replace the API with one that supports promises natively
You also need getUserInfo to have a return statement of its own.
You have to return some value from your getUserInfo function
If connection query doesn't support promise you should wrap it like this
/* get user info */
const getUserInfo = async(req) => {
let userID = req.cookies.userId;
if (!userID) return null;
return new Promise((resolve, reject) => {
connection.query('SELECT * FROM users WHERE id = ' + userID,
function(err, rows, fields) {
if (err) {
reject(err)
return;
}
// if user not found
if (rows.length === 0) {
resolve(null)
}
// if user found
else {
resolve(rows[0]);
}
});
});
}
I am new to node.js, and currently working on demo project so my requirement is to get count of userId which I am calling by function and this function is declared outside of route, but I am getting undefined but in same function getting count values but when I returned count still getting undefined in route.
Code:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
const usersQuery = "SELECT * FROM users";
dbConn.query(usersQuery,function(err,rows) {
if(err) {
console.log('this error',res);
} else {
let total=getCount(); // calling function placed outside
console.log(total);
}
});
});
Function declared outside to return count:
function getCount(){
const usersQuery = "SELECT count(id) as cnt FROM users";
dbConn.query(usersQuery,function(err,rows) {
if(err) {
console.log('failed to get count');
} else {
return rows; // retun count
}
})
}
You need to return the result of the query
function getCount(){
const usersQuery = "SELECT count(id) as cnt FROM users";
return dbConn.query(usersQuery,function(err,rows) {
if(err) {
console.log('failed to get count');
} else {
return rows; // retun count
}
})
}
Note that probably returns a Promise you need to handle correctly.
Finally I got the required output by using Promise() in node js
Code:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
const Query = "SELECT * FROM t1";
dbConn.query(Query,function(err,rows) {
if(err) {
// write some code
} else {
// call to promise
getData().then(function (outputVal) {
console.log(outputVal[0].Usr);
}).catch(function () {
// write error here
});
}
});
});
// Promise code
function getData() {
return new Promise(function (resolve, reject) {
// setTimeout(function () {
const MQuery = "SELECT count(id) as Usr FROM t2";
dbConn.query(MQuery , function (err, rows) {
if (err) {
reject();
} else {
resolve(rows);
}
// }, 1000);
})
})
}
A couple of things you should know:
The functions declared outside routes will be executed first in stack once the server starts even though you haven't called the specific route yet. By the time you call this function, it already holds undefined or null depending on the code inside the functions.
dbConn.query() is Promise. Which means it works synchronously.
if you need count of users, here is what you can do:
router.get('/', function(req, res, next) {
const usersQuery = "SELECT * FROM users";
dbConn.query(usersQuery,function(err,rows) {
if(err) {
console.log('this error',res);
} else {
let total= rows.length // you will get an array of users, therefore the number of users is equal to the length of the array
console.log(total);
}
});
});
Function checkExists is taking too long to execute. Tried to use await async function but had no effect. var exists = await checkExists(data.email); is returning undefined because not awaiting for checkExists.
I have my index.js:
const express = require('express');
const app = express();
require('./private/signUpAPI')(app);
app.listen(80, () => console.log('listening on 80'));
app.use(express.static('public'));
app.use(express.json({limit: '1mb'}));
And my signUpAPI.js:
const DataStore = require('nedb');
const express = require('express');
const database = new DataStore('private/database.db');
database.loadDatabase();
module.exports = function api(app){
app.use(express.json({limit: '1mb'}));
app.post('/signUpAPI', async (request, response) => {
console.log("Sign Up Request received!");
const data = request.body;
var exists = await checkExists(data.email);
console.log(exists)
console.log(data);
console.log("Added to DB");
console.log('-------------------------' + '\n');
database.insert(data);
const testData = {"status": "success"};
response.send(testData);
});
}
async function checkExists(email){
var exists = false;
database.find({"email": email}, async function(err, docs){
if (docs.length > 0){exists = true;}
console.log(docs.length);
return exists;
});
}
this is the node output when running index.js and calling the fetch('/signUpAPI'):
Sign Up Request received!
undefined
{
email: 'a',
username: 'a',
hashPass: 'da180265625ebeaf62f4ee1813bdc28faeaf79f0b2b329290758a1c095111ae8',
salt: 'g8VkTBV$+Bh35K9ns7Zt*9^CH#M=VELSzKUX=H3^+5kpFV=bEbVfXFtF*GGYHOa#'
}
Added to DB
-------------------------
37
I currently have 37 entries in the DB with the same data hence the console.log(docs.length) returning 37.
But this is executing last and appears at the bottom of the console when it should appear at the top.
Use https://www.npmjs.com/package/nedb-promise
so you can use await for database queries and you can change your code like this -
async function checkExists(email) {
const record = await database.findOne({ email });
console.log(record);
if (record) return true;
return false;
}
Functions you want to wait should return a promise in order to wait for response.
You either resolve the promise if the operation result is success or reject with an error.
The flow should like something like this;
async function func1()
{
try
{
var tmp = await func2();
console.log(tmp);
}
catch(err)
{
console.log(err);
}
}
async funcion func2()
{
return new Promise(async function (resolve, reject)
{
if(true)
{
resolve("success");
}
else
{
reject("error");
}
});
}
I have a class on my node server, each function of it returns something from another api, the first function that I will show does not use a parameter, it returns the items correctly, the second that uses the Make parameter, does not return anything, and does not point out error
function getInventory:
(this function works normally)
async getInventory() {
try {
let res = await axios.get(URL);
let data = res.data;
return data;
} catch (err) {
return err;
}
}
function getMakesNew(make): (this function works without errors but does not return anything)
async getMakesNew(make) {
try {
let res = await axios.get(URL);
let data = res.data;
let count = 0;
while (data != make) {
if (data[count].ID === make) {
return data[count].Name;
} else {
count++;
}
}
} catch (err) {
return err;
}
}
Calling the two functions on the routes:
// GetInventory
routes.get('/getInventory', async (req, res) => {
return res.json(await Vehicle.getInventory());
});
// getMakesNew
routes.get('/getMakesNew/:make', async (req, res) => {
let { make } = req.params;
return res.json(await Vehicle.getMakesNew(make));
});
function getMakesNew returns:
{}
return keyword is missing from your second function
For some reason, I can't get values returned from module.exports function from a separate custom module. I tried many ways from many sources from >10s researched posts. If you want to vote down, please read my bio or if you want to help I will be happy to accept your answer.
// restapi/index.js
module.exports = function gifs() {
giphy.search('Pokemon', function (err, res) {
return res.data[0];
});
}
// main server.js
var readapi = require('restapi')
console.log(readapi.gifs());
// Output:__________________
TypeError: readapi.gifs is not a function
You are exporting a function, not an object with a function and you are using a sync function (console.log) with an async operation.. it won't work.
You need to write it like this:
module.exports = function gifs(cb) {
giphy.search('Pokemon', function (err, res) {
if(err) { cb(err) }
else { cb(null, res.data[0]) }
});
}
----
var readapi = require('restapi')
readapi((err, data) => { console.log({err, data}) })
Remember the difference between:
module.export = {
hello: () => { console.log('world') }
}
// usage: require('./hello').hello()
module.export = () => { console.log('world') }
// usage: require('./hello')()
Try this code
module.exports.gifs = function gifs() {
return new Promise((resolve, reject) => {
giphy.search('Pokemon', function (err, res) {
if (err) reject(err);
else resolve(res.data[0]);
});
});
}
// main server.js
var readapi = require('restapi')
readapi.gifs().then(console.log);