return promise value from controller - node.js

I'm working with Node, Express and Objection.js.
My file structure is:
->Project Folder
->Controllers(folder)
->agenciaController.js
->Models(folder)
->Agencia.js
->index.js
in my index.js code is:
var Knex = require('knex');
var express = require("express");
var app = express();
var knexConfig = require('./knexfile');
var Model = require('objection').Model;
var knex = Knex(knexConfig.development);
Model.knex(knex);
var reqAgenciaController = require('./Controllers/agenciaController');
var agenciaController = new reqAgenciaController();
app.get("/agencias", function(req, res) {
var respuesta = agenciaController.getAgencias();
console.log("log3: "+respuesta);
});
And my agenciaController.js is:
var Agencia = require('../Models/Agencia');
module.exports = agenciaController;
function agenciaController() {
this.getAgencias = function() {
var retValue = "retvalue";
listaAgencias = [];
Agencia.query()
.then(function(agencias) {
listaAgencias = agencias;
console.log("log1: "+ listaAgencias);
});
console.log("log2: "+listaAgencias);
return listaAgencias;
}
}
My problem is that when I run the code, I get
log2:
log3: undefined
log1: [object Object, object Object].
But I need:
log1: [object Object, object Object].
log2: [object Object, object Object].
log3: [object Object, object Object].
My question is: is it possible to return listaApuestas from the controller to index.js, with the value obtained in the promise?

agenciaController.getAgencias() should be promosified using the promise library of your choice.
I recommend using bluebird.
The trick part is that if a promise reside in another promise you'll need to change your structure a little bit.
Sample agenciaController.js
var Promise = require("bluebird");
agenciaController = {
getAgencias: function(callback) {
this.queryAsync().then(function(respuesta) {
console.log("log2: "+ respuesta);
callback(false, respuesta);
})
},
query: function(callback) {
console.log("log1", {});
callback(false, { respuesta: "respuesta" })
}
}
Promise.promisifyAll(agenciaController);
module.exports = agenciaController;
Sample app.js
var AgenciaController = require('./agenciaController');
agenciaController.getAgenciasAsync().then(function(respuesta) {
console.log("log3: " + respuesta);
});
This will output:
log1 {}
log2: [object Object]
log3: [object Object]

Thank you for your help! Finally studying more about promises and following their examples, solved the problem.
Here is the code I use to solve the problem
My agenciaController.js:
var Agencia = require('../Models/Agencia');
module.exports = agenciaController;
function agenciaController() {
this.getAgencias = function() {
return Agencia.query()
.then(function(agencias) {
return agencias;
})
.catch(function(){
console.log("error en la promesa");
});
}
}
And my index.js:
var reqAgenciaController = require('./Controllers/agenciaController');
var agenciaController = new reqAgenciaController();
app.get("/agencias", function(req, res) {
var misAgencias;
var promise = new Promise(function(resolve, reject) {
if (agenciaController.getAgencias() === undefined){
reject("Error al llamar al getAgencias");
}else {
resolve(agenciaController.getAgencias());
}
});
promise
.then( agencias => {
misAgencias = agencias;
console.log(misAgencias);
res.send(misAgencias);
})
.catch(err => console.log("Error: "+err))
});

fn: async function() {
var output = '';
await myPromise()
.then((data) => {
output = data;
})
.catch((err) => {
output = "Error: " + err;
});
return ans;
}
Notice how we await for a promise to finish, before fn returns its value

Related

How do I await a nodejs request-promise object

I'm trying to return the results of an http request from a function and thought request-promise was supposed to return after an await. I obviously don't have this right. I get "undefined" returned from the function.
var s = getUrl();
console.log('result: ' + s)
function getUrl() {
var rp = require('request-promise');
var url = 'http://myserver.com?param=xxx';
rp(url)
.then(function (data) {
return data;
})
.catch(function (err) {
console.log(err);
});
}
How do I await the call so getUrl returns the data?
EDIT: After Kevin's comment. I tried to put this into a module and call it but it's returning [object Promise].
function getUrl(url, params) {
var rp = require('request-promise');
return rp(url + '?' + params)
.then(function (data) {
return data;
})
.catch(function (err) {
console.log(err);
});
}
async function getUpdate(o) {
var url = 'http://myserver.com';
var params = 'param=xxx';
var s = await getUrl(url, params);
return s;
}
exports.askVelo = (o) => {
var sRtn = '';
console.log(o.code);
switch (o.code) {
case 'g':
sRtn = getUpdate(o);
break;
}
console.log('heres rtn: ' + sRtn); // sRtn is [object Promise]
return sRtn;
}
getUpdate is now just returning [object Promise]... Why is that not working now?
I really needed to get the data in a synchronous fashion, so I finally gave up and used sync-request and skipped all the await/promise stuff.
sr = require('sync-request');
var url = 'http://myserver';
var qstring = 'param=xxx';
var res = sr('GET', url + '?' + qstring);
var str = res.body.toString();

NodeJS MVC asynchronous request

I'm getting undefined data from controller to model request in NodeJS.
My Model:
const db = require('../util/database');
module.exports = class Property {
constructor(pID) {
}
getPropertyByID(pID) {
let property = {};
db.execute('SELECT * From Properties Where PropertyID = ' + pID)
.then(res => {
const data = res[0][0];
if(data){
//console.log(data); This shows DATA if I remove the comment
property = data;
}
return property;
})
.catch(err => {
console.log(err);
});
}
}
Then, in my controller I tried to use the Model method.
exports.sendDataID = (req, res, next) => {
const propID = req.params.propID;
if(propID) {
const property = new Property();
const data = property.getPropertyByID(propID);
console.log(data);
}
};
The console.log(data) is returning undefined. Why is it happening?
Thanks
You may use async and await function to return a promise result.
async getPropertyByID(pID) {
let property = {};
try{
var res = await db.execute('SELECT * From Properties Where PropertyID = ' + pID)
property = res[0][0]; //not sure what res variable is
return data
}catch(error){
return error
}
}
and for use this function you only need to do this:
const propID = req.params.propID;
if(propID) {
const property = new Property();
const data = await property.getPropertyByID(propID);
console.log(data);
}
I recomend you to read about promises functions: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Promise

async await is not executing functions sequentially in express nodejs

I want to run 3 database query then render the 3 result objects to view, so I used async await to run queries first but seems its not waiting/working, always sending null objects to view before running queries. Cant find where I went wrong, I am using nodejs 12.16.1, not sure if its es6 supporting issue or sth else.
var express = require('express');
var router = express.Router();
var reviewModel = require.main.require('./models/review-model');
var propertyModel = require.main.require('./models/property-model');
router.get('/', async function(req, res){
try{
req.cookies['username'] == null ? loginCookie = null : loginCookie = req.cookies['username'];
var getPromoteInfo = await propertyModel.getPromoteInfo(function(result){
if(result!=null) return result;
});
var getPromoteReview = await reviewModel.getPromoteReview(function(result2){
if(result2!=null) return result2;
});
var getLatest3reviews = await reviewModel.getLatest3reviews(function(result3){
if(result3!=null) return result3;
});
res.render('index', {property:getPromoteInfo, rating:getPromoteReview, testimonials:getLatest3reviews, loginCookie});
}
catch(err){console.log(err);}
});
module.exports = router;
Model code:
var db = require('./db');
module.exports = {
getPromoteInfo: function(callback){
var sql = "select * from property where promote_status = 1;";
db.getResult(sql, null, function(result){
if(result){
callback(result);
}else{
callback(null);
}
});
}
}
You're using await on a function that does not return a Promise resulting in an undefined value. So in order for async/await to work, you could rewrite getPromoteInfo as follows:
var db = require('./db');
module.exports = {
getPromoteInfo: function(){
return new Promise( (resolve, reject) => {
var sql = "select * from property where promote_status = 1;";
db.getResult(sql, null, function(result){
if(result){
resolve(result);
}else{
// you can decide whether to reject or not if no records were found
reject();
}
});
});
}
}
In your express-handler you can then simply await this function call, without passing a callback:
const getPromoteInfo = await propertyModel.getPromoteInfo();
Note that you can check if your db-client/library supports promises out of the box - then you would not have to wrap your functions manually in a promise.

Getting empty array in nodejs

I am posting value But I am getting empty array . I know its node asynchronous problem . But I don't know how do i solve this. I have refer this following link:
How do I return the response from an asynchronous call?
But I could not able to understand . Kindly help me to understand promises and how do i use that in my code.
router.post('/inspection_list', function (req, res) {
var id = req.body.project_id;
console.log(id)
// res.send("ok")
db.inspection.findOne({'_id':id},(err,response)=>{
if(err){
console.log("error");
}
else{
console.log("Data")
var inspection = [];
var data = response.inspection_data;
var f = data.map(function (item) {
var fielduser = item.fielduser_id
db.fielduser.findOne({'_id': mongoose.Types.ObjectId(fielduser)},(err,user)=>{
console.log(user.owner_name);
console.log(item.inspection_name)
inspection.push({inspection_name:item.inspection_name,field_user_name : user.owner_name})
})
});
console.log(inspection) // Here am getting empty value
// setTimeout(function(){ console.log(inspection) }, 5000); my timeout code
}
})
});
router.post('/inspection_list', async function (req, res) {
var id = req.body.project_id;
try{
var response = await db.inspection.findOne({'_id':id})
var inspection = [];
var data = response.inspection_data;
for ( var i = 0; i<data.length; i++){
var item = data[i]
var fielduser = item.fielduser_id
var user = await db.fielduser.findOne({'_id': mongoose.Types.ObjectId(fielduser)})
inspection.push({inspection_name:item.inspection_name,field_user_name : user.owner_name})
}
}
catch(err){
throw err
}
})
This uses async and await, you can use it if you are using node version >=7.6
Also note the following:
router.post('/inspection_list', async function (req, res)
Handling each error seperately
router.post('/inspection_list', async function (req, res) {
var id = req.body.project_id;
try{
var response = await db.inspection.findOne({'_id':id})
}
catch(err){
// handle error here
throw err
}
var inspection = [];
var data = response.inspection_data;
for ( var i = 0; i<data.length; var item = data[i]
var fielduser = item.fielduser_id
try{
var user = await db.fielduser.findOne({'_id': mongoose.Types.ObjectId(fielduser)})
}
catch(err){
// handle error
}
inspection.push({inspection_name:item.inspection_name,field_user_name : user.owner_name})
}
})
Using mongoose would be the easy way out, it returns Promises for all query and save functions, so you'd simply do:
YourModel.findOne({params}).then(() => {...})
If you're unable to do that, in your case, a 'promisified' example would be:
var findAndFillArray = (project_id) => new Promise((resolve) => {
.... your previous code here ....
inspection.push({inspection_name:item.inspection_name,field_user_name :
user.owner_name})
if (data.length === inspection.length){ // Or some other preferred condition
resolve(inspection);
}
})
Then you'd call this function after you get the id, like any other function:
var id = req.body.project_id;
findAndFillArray(id).then((inspection_array) => {
res.send(inspection_array) // Or whatever
})
Now, map and all list functions are synchronous in JS, are you sure the error is due to that?

Gather multiple functions output on single route call and render to html in nodejs

Newbie to nodejs,trying to execute multiple functions output to html using nodejs,express and mysql as backend.Need to execute 20 functions on single routing call to combine the output of 20 functions and render as json to html.
My app.js function
var express = require('express');
var router = express.Router();
var path = require('path');
var app = express();
var todo = require('./modules/first');
var todo1 = require('./modules/second');
var connection = require('./connection');
connection.init();
app.get('/', function(req,res,next) {
Promise.all([todo.class1.getUsrCnt(),todo.class1.getTotlAmt(),todo.class1.getTotlOrdrCnt(),todo.class1.getTotlCntRcds(),todo.class1.getTotlScsRcds(),todo.class1.getTotlFailRcds(),todo.class1.getTotlAmtRcds()])
.then(function(allData) {
res.addHeader("Access-Control-Allow-Origin", "http://hostname:8183/");
res.json({ message3: allData });
});
res.send(send response to html);
})
app.get('/second', function(req,res,next) {
Promise.all([todo1.class2.getUsr........])
.then(function(allData) {
res.addHeader("Access-Control-Allow-Origin", "http://hostname:8183/");
res.json({ message3: allData });
});
res.send(send response to html);
})
var server = app.listen(8183, function(){
console.log('Server listening on port '+ server.address().port)
});
My todo.js is
var connection = require('../connection');
var data = {},obj={};
var d = new Date();
var month = d.getMonth() + 1;
var year = d.getFullYear();
obj.getUsrCnt = function getUsrCnt(callback) {
connection.acquire(function(err, con) {
con.query(query1, function(err, result) {
con.release();
data.usrs_cnt = result[0].some;
})
});
}
obj.getTotlAmt = function getTotlAmt(callback) {
connection.acquire(function(err, con) {
con.query(query2, function(err, result) {
con.release();
data.total_amt = result[0].some1;
})
});
}
obj.getTotlOrdrCnt = function getTotlOrdrCnt(callback) {
connection.acquire(function(err, con) {
con.query(query3, function(err, result) {
con.release();
data.total_orders = result[0].some2;
})
});
}
.
.
. functions go on
exports.class1 = obj;
Getting undefined in the promise all and unable to render to the html file.
Not sure about the code you wrote, but as I understand you want to call all the functions, get all the results and return back to the user?
so you can use many libraries that waits for several calls for example, promise based:
Promise.all([todo.getUsrCnt('dontcare'), todo.getTotlAmt('dontcate')])
.then(function(allData) {
// All data available here in the order it was called.
});
as for your updated code, you are not returning the data as promises, you assigning it to the local variable.
this is how your methods should look:
obj.getUsrCnt = function getUsrCnt(callback) {
var promise = new Promise(function(resolve, reject) {
connection.acquire(function(err, con) {
if(err) {
return reject(err);
}
con.query(query1, function(err, result) {
con.release();
resolve(result[0].some);
})
});
});
return promise;
}
as you can see here, I am creating a new promise and returning it in the main function.
Inside the new promise I have 2 methods: "resolve", "reject"
one is for the data and one is for errors.
so when you use the promise like this:
returnedPromise.then(function(data) {
//this data is what we got from resolve
}).catch(function(err) {
//this err is what we got from reject
});
you can see that a promise can or resolved or rejected,
do this to all the methods, and then you start seeing data

Resources