JS: ERROR: "Promise { <pending> }" with Sockets - node.js

I'm having a problem with a Promise, when I try to retrieve the data it says Promise { <pending> } I already looked for some information about that but I cannot understand how to end it.
If anyone can help me I would be appreciated.
Thanks in advance
/bucket.js
'use strict'
const connection = require('../server/models'),
oracledb = require('oracledb'),
conexion = oracledb.getConnection(connection)
oracledb.outFormat = oracledb.OBJECT
module.exports = (data) => {
console.log("RES: ", filter(data));
return filter(data)
}
const filter = (value) => {
return conexion
.then(con => {
return con.execute(
`SELECT id_application, name, description, creation_date ` +
`FROM application `
).then(bucket => {
return con.execute(
`SELECT id_definition, id_application, field_name_original,
field_name_new, column_name, position, id_type_data,
field_size, creation_date, description, filter, visible ` +
`FROM definition ` +
`WHERE id_application in (${getApp(value.data)}) ` +
`AND ${value['search']} = '${value['value']}' `
).then(definitions => { return creaJSON(bucket, definitions) } )
.catch(error => { return {"error": error} })
})
.catch(error => { return {"error": error} })
})
.catch(error => { return {"error": error} })
}
const getApp = (value) => {
return value.map(obj => {
return `'${obj.ID_APPLICATION}'`
})
}
const creaJSON = (buckets, definitions) => {
var df = new Array()
buckets['rows'].map(obj => {
definitions['rows'].map(def => {
if(obj['ID_APPLICATION'] == def['ID_APPLICATION']) df.push(def)
})
obj['Definitions'] = df
df = []
})
return buckets.rows
}
UPDATED
My error wasnt only in the code above. I'm using sockets and also with the Bergi answer I couldn't had my response in the client. I had the next code:
socket.on('bucketVisibleT', (data) => {
buckets = {data:data,search:'VISIBLE',value:'T'}
io.sockets.emit('bucketVisibleFs', require('./bucket')(buckets))
})
so I had to change with the next one, and now I have my response in my client.
socket.on('bucketVisibleT', (data) => {
buckets = {data:data,search:'VISIBLE',value:'T'}
require('./bucket')(buckets).then(res => {
io.sockets.emit('bucketVisibleTs', res)
})
})
I apologise because I didn't give a good explanation of my problem but I thought it was in my first code

filter returns a promise, so like with the other promise-returning functions you need to chain a then call to it if you want to do something with the result:
module.exports = (data) =>
filter(data).then(res => {
console.log("RES: ", res);
return res;
});

Related

Nodejs Function is returning undefined

I have 2 files index.js and models.js
my index.js file requires the model.js file
const models = require("./modules/models.js");
app.post('/message', (req, res) => {
const _lead = models.createLead(req.body)
_lead.then(l => {
console.log("resulted in lead", JSON.stringify(l))
// GETTING UNDEFINED HERE
})
// const _message = await models.createMessage(req.body.message)
res.send();
});
My models.js file has a functions that contain Promises
const createLead = async function (payload) {
// Find lead
let result
new Promise((resolve, reject) => {
findLeadById(payload.lead.rid).then(async _lead => {
// If a lead has not been found
if (!_lead) {
if(payload.companyRid != payload.lead.rid){
await db.collection('leads').add(payload.lead).then((l) => {
result = payload.lead
result['id'] = l.id
})
}
} else {
result = _lead
}
}).then(() => {
console.log(" result of create lead ",JSON.stringify(result))
resolve(result)
}).catch(error => {
error.log("reject", error)
reject(error)
})
})
}
const findLeadById = async function (lead) {
new Promise(async (resolve, reject) => {
const ref = db.collection('leads');
console.log("finding lead", JSON.stringify(lead))
await ref.where("rid", "==", lead).get().then((s) => {
let obj = null
if(s){
s.forEach(doc => {
console.log("found the lead in loop", JSON.stringify(doc.data()))
obj = doc.data()
obj['id'] = doc.id
})
}
resolve(obj)
}).catch(error => {
error.log("reject", error)
reject(error)
})
})
}
exports.createLead = createLead;
exports.findLeadById = findLeadById;
The model.js returns an object as expected
console.log(" result of create lead ",JSON.stringify(result))
However, I'm expecting to see that same object in the index.js in the then block but I'm getting undefined.
console.log("resulted in lead", JSON.stringify(l))
// GETTING UNDEFINED HERE
The following is not waiting for the associated functions to finish
const _lead = models.createLead(req.body)
I have also tried adding async and await which also didn't work
const _lead = await models.createLead(req.body).then(res => {console.log("result", res) // Still undefined
})
I think you can use resolve for any success response, and reject for error response. Ex:
await db.collection('leads').add(payload.lead).then((l) => {
let result = payload.lead
result['id'] = l.id
resolve(result)
})

Problem to use a Map in Firebase Functions

I am trying to get the length of a Map and I keep getting "undefined". Could please someone tell me what am I doing wrong?
This is the part of the code that gives me problems.
const GYMdetail: { [key: string]: number} = {};
GYMdetail[`${doc.data().name} (${doc.data().personalID})`] = 650;
const subtotal = 650 * GYMdetail.size;
This is the complete function code
export const addGymMonthlyExpense =
functions.https.onRequest((request, response) => {
const query1 = admin.firestore().collection("users");
const query = query1.where("subscriptions.gym.active", "==", true);
query.get()
.then(async (allUsers) => {
allUsers.docs.forEach(async (doc) => {
if (doc != undefined) {
const houseForGym = doc.data().subscriptions.gym.house;
await admin.firestore()
.doc(`houses/${houseForGym}/expenses/2022-04`)
.get().then((snapshot) => {
if (snapshot.data() == undefined) {
console.log(`${houseForGym}-${doc.data().name}: CREAR!!`);
} else if (snapshot.data()!.issued == false) {
let detail: { [key: string]: any} = {};
const GYMdetail: { [key: string]: number} = {};
detail = snapshot.data()!.detail;
GYMdetail[
`${doc.data().name} (${doc.data().personalID})`
] = 650;
const subtotal = 650 * GYMdetail.size;
detail["GYM"] = {"total": subtotal, "detail": GYMdetail};
snapshot.ref.set({"detail": detail}, {merge: true});
}
return null;
})
.catch((error) => {
console.log(
`${houseForGym} - ${doc.data().name}: ${error}`);
response.status(500).send(error);
return null;
});
}
});
response.send("i");
})
.catch((error) => {
console.log(error);
response.status(500).send(error);
});
});
Since you are executing an asynchronous call to the database in your code, you need to return a promise from the top-level code; otherwise Cloud Functions may kill the container when the final } executes and by that time the database load won't be done yet.
So:
export const addGymMonthlyExpense =
functions.https.onRequest((request, response) => {
const query1 = admin.firestore().collection("users");
const query = query1.where("subscriptions.gym.active", "==", true);
return query.get()
...
Next you'll need to ensure that all the nested get() calls also get a chance to finish before the Functions container gets terminated. For that I recommend not using await for each nested get call, but a single Promise.all for all of them:
query.get()
.then(async (allUsers) => {
const promises = [];
allUsers.docs.forEach((doc) => {
const houseForGym = doc.data().subscriptions.gym.house;
promises.push(admin.firestore()
.doc(`houses/${houseForGym}/expenses/2022-04`)
.get().then((snapshot) => {
...
});
});
response.send("i");
return Promise.all(promises);
})
.catch((error) => {
console.log(error);
response.status(500).send(error);
});

Express router not awaiting the forEach loop

Express router is not awaiting my forEach loop and sends the old unmanipulated object as a response instead of the new manipulated data.
Here I am using Sequalize as my ORM.
router.get('/', async (req,res) => {
try {
let trainings = await db.Training.findAll();
let locations = await db.Location.findAll();
await locations.forEach(location => {
trainings.forEach(training => {
if(location.trainingId == training.id){
training["location"] = location
}
})
})
res.status(200).json({
training:trainings
})
} catch(err) {
console.log(err);
res.status(404).json({
message : err
})
}
})
Basically you are using the await keyword against a synchronous process which is
locations.forEach(location => {
trainings.forEach(training => {
if(location.trainingId == training.id){
training["location"] = location
}
})
})
These lines of code doesn't return any promise or behave like a promise. So one solution can be having a function
function modify(trainings,locations){
return new Promise((resolve,reject)=>{
locations.forEach(location => {
trainings.forEach(training => {
if(location.trainingId == training.id){
training["location"] = location
}
})
})
resolve('done')
})
}
then have it like this
let trainings = await db.Training.findAll();
let locations = await db.Location.findAll();
await modify(trainings,locations)
or you can simply remove the await keyword from your current state of code.

Promise.resolve return undefined from jest mock function

I have a function which makes API call and based on what would return by the first API call it makes the second API call. But the first API always returns undefined
getTotalCount = async () => {
const { showCountCallBack, showCount } = this.props;
try {
const response = await showCount();
const count = isEmpty(response.result);
if (count) {
console.log(" success");
} else {
showCountCallBack({ ...this.state });
}
} catch (e) {
console.log("error");
}
};
describe("component", () => {
let shallowComponent;
let shallowComponentInstance;
const showCountMock = jest.fn(() => Promise.resolve({ result: [] }));
const showCountCallBackMock = jest.fn(() => Promise.resolve({ result: [] }));
beforeEach(() => {
showCountMock.mockReset();
shallowComponent = shallowWithTheme(
<Component
showCount={showCountMock}
showCountCallBack={showCountCallBackMock}
/>
);
shallowComponentInstance = shallowComponent.instance();
});
it("viewMapping", () => {
shallowComponentInstance.getTotalCount();
expect(showCountMock).toHaveBeenCalledTimes(1);
expect(showCountCallBackMock).toHaveBeenCalledTimes(1);
});
});
After struggling for hours. I have found the cause. It was mockReset causing this issue.
It reset return value as well. so I just removed the mockReset from code. Better to use mockClear here

How can I get a value returned from a then clause when select data using mysql

I am trying to finish a login functionality with mysql and express. I got a work_id and a user_password, and I want to use the work_id to find whether the user exists in my database. I use promise to do this, I can log the selected user information in the console, but the promise is always pending, and the web storm console didn't terminate.
What I want is a boolean value from the promise, whether the user exists or not.
Here is my code:
query.js.
const pool = require('./connect');
module.exports = {
query: function (sqlString, params) {
return new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
if (err) {
reject(err)
} else {
connection.query(sqlString, params, (err, rows) => {
if (err) {
reject(err)
} else {
resolve(rows)
}
connection.release()
})
}
})
})
}
}
sqlCRUD.js, about the sql statement
const user = {
queryByWorkId: 'select * from user_info where work_id=?',
queryAll: 'select * from user_info',
resetPassword: 'update user_info set user_password = ? where work_id = ?',
};
user.js, I execute the test here.
const Model = require('./main')
const crypto = require('crypto')
const _ = require('./query')
const $sqlQuery = require('./sqlCRUD').user
class User{
// others
static findOne(form={}) {
const { work_id, user_password } = form
return _.query($sqlQuery.queryByWorkId, work_id)
.then(res => {
console.log(res)
if (res.length > 0) {
const u = res[0]
return u
}
return false
})
.catch(err => {
console.log('User.findOne error', err)
return {
errmsg: JSON.stringify(err)
}
})
}
Here is my test, in user.js
const test = () => {
const form = {
work_id: '007',
user_password: 'root',
}
const r = User.findOne(form)
console.log('r', r)
}
And this is the output:
I am not allowed to embed a picture here, so SO generates a link
I got confused about this: in my query.js file, I return a promise, in my User.findOne(form={}) method, I call it with a then and catch,
return _.query($sqlQuery.queryByWorkId, work_id).then(res => console.log(res)).catch(err => console.log(err)), but the console did't terminate, and I just got a Promise { }.
What's wrong with my code? How can I get a value returned from a then clause in promise when select data using mysql? Thanks in advance.

Resources