I'm learning to develop a Rest API using NodeJs with Express JS. I build a controller to do my stuff inside it. I want to call a local function inside the controller but it is not working. I always get not defined error.
Hear is my Controller,
const db = require('../config/db');
class TransactionController {
constructor(){
}
generateCustomerTransaction(req, res) {
const program_id = req.params.program_id;
const customerList = getCustomerList(program_id); //error here
//Do some business logics
return res.json(result);
};
getCustomerList(program_id) {
//Do some query to get a list of result
return results;
}
}
module.exports = SeatExcelController;
Everything seems simple like others languages but I get
ReferenceError: getCustomerList is not defined
I have no idea how to simply call a local function.
Please help. Thanks a lot.
To be able to access your function that way it needs to be defined on the package scope outside the class as in:
const db = require('../config/db');
const getCustomerList(program_id) = () => {
// Do some query to get a list of result
return results;
}
class TransactionController {
generateCustomerTransaction(req, res) {
const program_id = req.params.program_id;
const customerList = getCustomerList(program_id); //error here
//Do some business logics
return res.json(result);
};
}
module.exports = SeatExcelController;
Or call your function with this before the call as in:
const db = require('../config/db');
class TransactionController {
generateCustomerTransaction(req, res) {
const program_id = req.params.program_id;
const customerList = this.getCustomerList(program_id); //error here
//Do some business logics
return res.json(result);
};
function getCustomerList(program_id) {
// Do some query to get a list of result
return results;
}
}
module.exports = SeatExcelController;
I would go for the first option if the function doesn't need to access any class variables.
You could also make this a static function if it is not related to the class:
static getCustomerList(program_id) {
//Do some query to get a list of result
return results;
}
and call the function like this:
TransactionController.getCustomerList(program_id)
or just call the function using the this keyword. Because the way you code it now, the function is belonging to your class and class dependent.
: this.getCustomerList(program_id)
Related
I tried to make function for my project in the service. This service need to check is user exists in my database, but my function(this function is checking) inside the class return undefined.
This is my code:
const express = require("express");
const mongoDB = require('mongodb').MongoClient;
const url = "here I paste url to my databse(everything is good here)";
class CheckService {
isUserExists(username) {
mongoDB.connect(url, (error, connection) => {
if (error) {
console.log("Error", '\n', error);
throw error;
}
const query = {name: username};
const db = connection.db("users");
const result = db.collection("users").find(query).toArray(
function findUser(error, result) {
if (error) {
throw error;
}
const arr = [];
if (result.value === arr.value) {
console.log(false);
connection.close();
return false;
} else {
console.log(true);
console.log(arr);
console.log(result);
connection.close();
return true;
}
});
console.log(result);
});
}
}
module.exports = new CheckService();
I imported my service to another service:
const checkService = require('./check.service');
After this, I invoked my function from my service like this:
console.log('function:',checkService.isUserExists(username));
I expected good result, but function doesn't return, that I want, unfortunately.
Please help!
There are two problems with your function
it doesn't return anything
toArray() is a promise, so your console.log probably just prints a promise.
Probably you're looking for something like this:
class CheckService {
async isUserExists(username) {
const connection = await mongoDB.connect(url);
const query = {name: username};
const db = connection.db("users");
const result = await db.collection("users").find(query).toArray();
connection.close();
return result.length !== 0;
}
}
You'd then invoke it with something like
await new CheckService().isUserExists(username);
Though, it's worth noting that you probably don't need toArray and instead could use findOne or even count() since all you care about is existence. I probably also wouldn't instantiate a new connection each time (but that's not super relevant)
2 things wrong here. Firstly the first comment is correct. You're only logging the result and not passing back to the caller. Secondly, a quick peek at the mongo docs shows that retrieval methods are promises. You need to make the function async and add awaits where needed.
Mongo:
https://www.mongodb.com/docs/drivers/node/current/fundamentals/crud/read-operations/retrieve/
Promises:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
I'm sure this issue is from my lack of async/await knowledge or general best practices in general. However, I cannot figure out what I am doing wrong. I'm looking to pull a value from my firestore database, include it into an array of "global variables" and then call it when ever I need it in other modules. However when I check the array pulled in the test function, it always returns a promise. The below code is an example of the last thing I tried.
index.js
const vars = require('./variables');
test();
async function test() {
console.log('Expect database value', await vars.global()['lovePizza']);
}
variables.js (this is working, array updates)
const db = require('./database');
Let globalVars = {
lovePiza : '',
}
const variables = {
async global() {
globalVars['lovePizza'] = (globalVars['lovePizza'] === '') ? db.getLovePizza() : globalVars['lovePizza'];
return globalVars;
}
}
module.exports = variables;
database.js (this is working, value gets pulled from db)
const database = {
async getLovePizza() {
const usersRef = db.collection('accounts').doc('user1');
const doc = await usersRef.get();
if (!doc.exists) {
console.log('No such document!');
} else {
return doc.data()['lovePizza'];
}
}
}
module.exports = database;
Terminal Response:
Expect database value undefined
I saw a problem in your variables.js, I hope the problem is solved with these changes, use await before db.getLovePizza()
use try/catch when you use async/await
const db = require('./database');
Let globalVars = {
lovePiza : '',
}
async global() {
if(globalVars['lovePizza'] === ''){
try {
let result = await db.getLovePizza()//use await
console.log(result);
globalVars['lovePizza'] = result
} catch (error) {
console.log(error)
//do somthing for error handlig like throw
}
}
else{
globalVars['lovePizza'] = globalVars['lovePizza'] //I think there is no need for this
}
return globalVars;
}
index.js
test() {
let result = await vars.global()
console.log('Expect database value', result);// added to question
console.log('Expect database value', result['lovePizza']);// added to question
}
I've been doing some reading on modularizing my code and decided to export some functions to a separate file and include them in my main function once it's called. Only my config of my website is not returning if I'm calling it:
// Export from my controller
// File: Controller.js
exports.site_config = function(company, data) {
siteConfig.find({"company" : company}, function data (err, siteConfig, data) {
// Console.log(siteConfig[0]) // Works
return siteConfig[0] // This return is not working
})
// Only here returns works....
}
// File: Index.js
const siteController = require('../controllers/site');
console.log(siteController.site_config('company2')) // nothing return
your find function return a callback you can do something like this:
// Export from my controller
// File: Controller.js
exports.site_config = function(company, data, callback) {
siteConfig.find({"company" : company}, function (err, siteConfig, data) {
callback(siteConfig[0]);
})
}
// File: Index.js
const siteController = require('../controllers/site');
console.log(siteController.site_config('company2', null,function (result) {
console.log(result)
}))
In nodejs- express js , you need to pass function as callback .
when result is available or some error occurred in code return them in callback;
// File: Controller.js
write your function inside module.exports :
module.exports = {
var site_config = function(company,callback) {
siteConfig.find({"company" : company}, function(err, data)
{
if(!err && data){
// no error and data is available , so pass err as null and data as data[0] to callback
return callback(null,data[0]);
}else{
// error occured , pass err as err and data = null to callback
return callback(err,null);
}
});
}
}
in you File: Index.js , require file Controller.js
const siteController = require('../controllers/Controller');
siteController.site_config('company2',function(err,data){
console.log(data);
});
This is a special case of this problem. Synchronous code can be transformed to asynchronous but not vice versa.
Mongoose has been supporting promises for a long time, callback API is legacy. This is a use case for them.
A module should export a promise of configuration object. A more concise way to retrieve a single document is findOne:
exports.site_config = function(company, data) {
return siteConfig.findOne({"company" : company});
};
And is consumed as a promise. There should be promise chain, up to to application entry point if needed:
// inside `async` function:
const siteController = require('../controllers/site');
const config = await siteController.site_config('company2');
I'm new to Mongoose. I wrote a statics method and a instance method for a Mongoose schema named 'questionSchema' and exported it like so:
var questionSchema = new Schema({
...
})
questionSchema.methods.createQuestion = function(){
return this.save(function(err){
if(err){
return err
};
return 'Saved the question';
});
};
questionSchema.statics.getAllQ = function(){
return this.find({}, function(err, res){
if(err){
return err
};
return res;
});
}
module.exports = mongoose.model('Question', questionSchema)
Then in a route in my Node/Express server, I imported the it as a model, and tried calling the static method, which should return all the documents under the Question model:
const Question = require('../models/question.js');
...
router.post('/qcrud/submit', (req, res) => {
let reqBody = req.body;
var newQuestion = new Question({reqBody});
newQuestion.createQuestion();
})
router.get('/qcrud/getAll',(req, res) => {
let qArr = Question.getAllQ()
res.send(qArr);
});
However, it returns a Query object, not an array like I expected. I looked around and saw on MDN that
'If you don't specify a callback then the API will return a variable
of type Query.'
I did specify a callback, but still got the Query object. First of all, am I using my static and instance methods right? Are the documents even saving? And how do I access the array documents saved?
If you're using Node 8.x you can utilize async/await
This way your code will look more synchronous:
questionSchema.statics.getAllQ = async () => {
return await this.find({});
}
router.get('/qcrud/getAll',async (req, res) => {
let qArr = await Question.getAllQ();
res.send(qArr);
});
You can find a really nice article that is explaining how to use Mongoose with async/await here.
I am currently developing a bot using wit.ai. I am quite new to node.js. Basically, I am following the guide provided by node-wit lib. I construct my wit object by:
const wit = new Wit({
accessToken: WIT_TOKEN,
actions,
logger: new log.Logger(log.INFO)
});
In my actions, I have something like:
const actions = {
send({sessionId}, {text}) {
//my sending action goes here.
},
firstaction({context, entities,sessionId}) {
var data = async_function();
context.receiver = data;
return context;
}
}
The issue is that whatever comes after async_function will be executed first. I tried to let async_function return a promise. However, this wouldn't work since whatever comes after my first action in node-wit library will be executed first without waiting for the context to return. I don't want to modify the node-wit library.
Any idea that would solve my issue is appreciated!
you can use async library for asynchronous call
https://caolan.github.io/async/docs.html
const async = require('async')
const actions = {
send({sessionId}, {text}) {
//my sending action goes here.
},
firstaction({context, entities,sessionId}) {
async.waterfall([function(callback) {
var d = async_function();
// if err pass it to callback first parameter
// return callback(err)
callback(null,d);
}], function(err, result) {
if(err) {
return err;
}
var data = result;
context.receiver = data;
return context;
})
}
}