Run promises sequentially in node.js - mysql

I'm still figuring node.js and promises out.
There's an area in my code where I would like my sql statements to run sequentially.
I would like one sql statement to run once one sql statement is done. I'm not sure if I am implementing promises properly.
one of the sql statements:
var selectbotagentstoadd=new Promise((resolve,reject)=>{
var sql='SELECT tbltestbotagentstoadd.AgentID FROM tbltestbotagentstoadd WHERE tbltestbotagentstoadd.IDNumber=? AND tbltestbotagentstoadd.MSISDN=?;'
DB.query(sql,[agentidpassnum,agentnumber],function(err,results){
if (err){
return reject(err);
};
return resolve(results);
});
})
the promise statement:
await insertbotagentstoadd.then(()=>{
console.log("done with one");
})
.then(()=>{ selectbotagentstoadd.then((results)=>
{
AgenttoaddIDStore=[];
results.forEach(agent=>{
AgenttoaddIDStore.push({
AgentID:agent.AgentID
});
ctx.session.tempAgentID=agent.AgentID
});
console.log("agent ID: "+ctx.session.tempAgentID);
console.log("done with two");
})})
.then((results)=>{insertcctblricaagents
console.log("done with three");
})
.then((results)=>{selectcctblricaagents.then((result)=>{
console.log(result);
AgentnewIDStore=[];
result.forEach(agent=>{
AgentnewIDStore.push({
AgentID:agent.AgentID
})
ctx.session.AgentID=agent.AgentID
})
console.log("cctblricaagents agent ID: "+ ctx.session.AgentID);
console.log("done with four");
})})
.then(insertcctblricaagentsnum.then((result)=>{
console.log("done with five");
}))
.then(selectcctblricaagentsnum.then((result)=>{
console.log(result)
AgentIDStore=[];
result.forEach(agent=>{
AgentIDStore.push({
AgentID:agent.AgentID,
MainNumber:agent.MainNumber,
})
ctx.session.AgentID=agent.AgentID
ctx.session.agentnumber=agent.MainNumber
})
console.log("cctblricaagentsnum agent ID: "+ ctx.session.AgentID);
console.log("done with six");
}))
.then(insertcctblintblbotagents.then((result)=>{
console.log("done with seven");
}));
The results I get from the terminal:
Agent number: 27815567777
done with one
done with three
agent ID: 89
done with two
[]
cctblricaagents agent ID: null
done with four

If you properly return the promises in each of the then blocks, it should execute sequentially.
simplifying your code, for ex:
await insertbotagentstoadd
.then(() => {
console.log("done with one");
})
.then(() => selectbotagentstoadd)
.then((res) => {
console.log("done with two");
return res;
})
.then((results) => insertcctblricaagents)
.then((res) => {
console.log("done with three");
return res;
})
.then((results) => selectcctblricaagents)
.then((res) => {
console.log("done with four");
return res;
})
.then(() => insertcctblricaagentsnum)
.then((res) => {
console.log("done with five");
return res;
})
.then(() => selectcctblricaagentsnum)
.then((res) => {
console.log("done with six");
return res;
})
.then(() => insertcctblintblbotagents)
.then((res) => {
console.log("done with seven");
return res;
});
Edit:
How it will look with your calculation included:
await insertbotagentstoadd
.then(() => {
console.log("done with one");
})
.then(() => selectbotagentstoadd)
.then((results) => {
AgenttoaddIDStore = [];
results.forEach((agent) => {
AgenttoaddIDStore.push({
AgentID: agent.AgentID,
});
ctx.session.tempAgentID = agent.AgentID;
});
return AgenttoaddIDStore;
})
.then((res) => {
console.log("done with two");
return res;
})
.then((results) => insertcctblricaagents)
.then((res) => {
console.log("done with three");
return res;
})
.then((results) => selectcctblricaagents)
.then((result) => {
AgentnewIDStore = [];
result.forEach((agent) => {
AgentnewIDStore.push({
AgentID: agent.AgentID,
});
ctx.session.AgentID = agent.AgentID;
});
return AgentnewIDStore;
})
.then((res) => {
console.log("done with four");
return res;
});

Related

update query in promise not running

please help, the update query isn't running in my promise.
It just skips to the last statement "done with six". The row that it's meant to update in the database table doesn't get updated. how can I make the update query run successfully?
1. crud statements(select+insert statements) that I've placed above the update statement
code would be here
2. update statement that does not seem to run
var insertcctblintblbotagents = await new Promise((resolve, reject) => {
var sql='UPDATE db.tblagentstoadd SET db.tblagentstoadd.ccAgentID =? WHERE
db.agentstoadd.AgentID=? ;';
DB.query(sql,[ctx.session.AgentID, ctx.session.tempAgentID],function(err,result){
if (err){
return reject(err);
};
return resolve(result);
})
})
3. the promise statement (allows the crud statements to run synchronously because the statements are dependent on one another)
await insertbotagentstoadd
.then(() => {
console.log("done with one");
})
.then(() => selectbotagentstoadd)
.then((results) => {
AgenttoaddIDStore = [];
results.forEach((agent) => {
AgenttoaddIDStore.push({
AgentID: agent.AgentID,
});
ctx.session.tempAgentID = agent.AgentID;
});
return AgenttoaddIDStore;
})
.then((res) => {
console.log("agent ID: "+ctx.session.tempAgentID);
console.log("done with two");
return res;
})
.then((results) => insertcctblricaagents)
.then((res) => {
console.log("done with three");
return res;
})
.then((results) => selectcctblricaagents)
.then((res) => {
console.log("done with four");
return res;
})
.then((res)=>selectcctblricaagentsnum)
.then((result)=>{
AgentNewIDStore=[];
result.forEach((agent)=>{
AgentNewIDStore.push({
AgentID:agent.AgentID,
MainNumber:agent.MainNumber,
});
ctx.session.AgentID=agent.AgentID;
ctx.session.agentnumber=agent.MainNumber;
});
return AgentNewIDStore;
})
.then((res)=>{
console.log("cctblricaagentsnum agent ID: "+ ctx.session.AgentID);
console.log("done with five");
return res;
})
.then((result)=>insertcctblintblbotagents) //Doesn't run this area of code
.then((res)=>{
console.log("done with six");
return res;
});
4.results displayed in the terminal or console
done with one
agent ID: 151
done with two
done with three
done with four
cctblricaagentsnum agent ID: 96661
done with five
done with six
It does run the query, but it runs before you intend it to... You execute the query when you define the promise, not when you "use" it. The code is looking weird so I won't redo everything, but I suggest you use awaits instead of a chain of then(), it will make things more readable. If you inline the promise you defined, things will work:
.then((result)=>insertcctblintblbotagents) //Doesn't run this area of code
To
.then((result)=>{
return new Promise((resolve, reject) => {
var sql='UPDATE db.tblagentstoadd SET db.tblagentstoadd.ccAgentID =? WHERE
db.agentstoadd.AgentID=? ;';
DB.query(sql,[ctx.session.AgentID, ctx.session.tempAgentID],function(err,result){
if (err){
return reject(err);
};
return resolve(result);
})
})

Asynch problem when fetching MySQL and EXPRESS

I'm trying to simple add a new property in an object. The array of objs is being fetched from my database and then I try to add a property which is also fetched from my database. Although when I try to manipulate it I'm receiving "undefined".
Is it indeed an asynch problem?
Am I doing any silly mistakes?
Those are questions that surrounds my head at the moment.
Code:
exports.getIndex = (req, res, next) => {
Report.fetchAll().then(([rows, fieldData]) => {
// console.log(rows);
const modifiedRows = rows.map(el => {
Report.fetchUserNameOfReport(el.UserInfo_idPessoa).then(([rows, fieldData]) => {
console.log(rows);
return {
...el,
userOfReport: 'Joao' //change later to smthing like rows.name
};
}).catch(err => console.log(err));
// return{
// ...el,
// userOfReport: 'Joao'
// };
});
res.render('user/index', { reports: rows, pageTitle: 'Social Reporter', path: '/' });
}).catch(err => console.log(err));
};
Obs This works if comment this out and comment Report.fetchUserNameOfReport function->
// return{
// ...el,
// userOfReport: 'Joao'
// };
Expected result:
{
idComplaint: 83059,
title: '4444',
description: '4444',
image: '4444',
location: '4444',
UserInfo_idPessoa: 80068,
userOfReport: 'Joao'
}
Actual result:
undefined
Thank you in advance!
You never return anything in your .map, so all of the values of modifiedRows will be undefined. You can map them all to promises to get all the values, and then access the modified rows once you wait for all of the promises to resolve. Also, you're shadowing your variable by declaring rows and fieldData multiple times:
exports.getIndex = (req, res, next) => {
Report.fetchAll().then(([rows, fieldData]) => {
// console.log(rows);
const modifiedRowPromises = rows.map(el => {
return Report.fetchUserNameOfReport(el.UserInfo_idPessoa).then(([rows2, fieldData2]) => {
console.log(rows2);
return {
...el,
userOfReport: 'Joao' //change later to smthing like rows2.name
};
});
});
Promise.all(modifiedRowPromises).then(modifiedRows => {
res.render('user/index', { reports: modifiedRows, pageTitle: 'Social Reporter', path: '/' });
}).catch(console.log);
}).catch(err => console.log(err));
};
Alternatively, if you use async/await syntax, this can be achieved much more cleanly:
exports.getIndex = async (req, res, next) => {
try {
const [rows, fieldData] = Report.fetchAll();
const modifiedRowPromises = rows.map(async el => {
const [rows2, fieldData2] = await Report.fetchUserNameOfReport(el.UserInfo_idPessoa);
return {
...el,
userOfReport: 'Joao' //change later to smthing like rows2.name
};
});
const modifiedRows = await Promise.all(modifiedRowPromises);
res.render('user/index', { reports: modifiedRows, pageTitle: 'Social Reporter', path: '/' };
} catch (err) {
console.log(err);
}
};

create data to three tables at once with Sequelizer

I want to get data from form and based on that, add data to three tables in mySQL, I use Sequelize to do so, However I don't how to do so, my current idea gives error:
Unhandled rejection Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers
after they are sent to the client
My code is like this:
app.post("/device/add", (req, res) => {
db.Devices.create({
device_id: req.body.device_id,
server: req.body.server,
type: req.body.type
})
.then(result => {
res.json(result);
})
.catch(err => {
throw err;
});
db.Modules.create({
device_id: req.body.device_id,
device_options: req.body.device_options,,
sleep_options: req.body.sleep_options
})
.then(result => {
res.json(result);
})
.catch(err => {
throw err;
});
db.Tests.create({
device_id: req.body.device_id,
gsm_tests: req.body.gsm_tests,
led_tests: req.body.led_tests,
})
.then(result => {
res.json(result);
})
.catch(err => {
throw err;
});
});
can I somehow create it in one response? Or how to make it work
The problem is that you are trying to send again a response after you have sent one.
For more clarification, refer here
You can use Promise.all() to accumulate the results and then send it in one res.json() call.
const createDevice = db.Devices.create({
device_id: req.body.device_id,
server: req.body.server,
type: req.body.type
})
const createModules = db.Modules.create({
device_id: req.body.device_id,
device_options: req.body.device_options,
sleep_options: req.body.sleep_options
})
const createTests = db.Tests.create({
device_id: req.body.device_id,
gsm_tests: req.body.gsm_tests,
led_tests: req.body.led_tests,
})
Promise
.all([createDevice , createModules , createTests ])
.then(result=> {
res.json({
devices: result[0],
modules: result[1],
test : result[2]
});
})
.catch(err => {
throw(err);
});

TypeError: Cannot read property 'splice' of undefined

I've created a fixture file to handle my JSON datas used to write tests.
Before each test, I want my data to be filled with seed data.
After each test, I want my data to be empty
Courses.json :
[
{
"id": 1,
"title": "Ma course"
}
]
CoursesFixture.js :
const { courseList } = require('./courses')
mockData = [
{
"id": 1,
"title": "Ma course"
}
]
module.exports = {
up: () => {
courseList.splice(0)
courseList.push.apply(courseList, mockData)
},
down: () => {
courseList.splice(0)
}
}
CoursesTest.js :
const request = require("supertest")
require('chai').should()
const bodyParser = require("body-parser")
const app = require('./../../app')
app.use(bodyParser.json())
const listeDeCourses = require("../fixtures/courses")
const listeDeCoursesFixture = require("../fixtures/coursesFixture")
describe('Courses', () =>{
beforeEach(() => { listeDeCoursesFixture.up() })
afterEach(() => { listeDeCoursesFixture.down() })
describe('Delete course list', ()=>{
it("Should delete a list of course", ()=>{
return request(app).get('/course')
.then((res) => {
res.body.should.have.lengthOf(1)
request(app).delete('/course').send({"id":"1"})
.then((res) => {
res.body.should.have.lengthOf(0)
})
}).catch((err) =>{
throw new Error(err);
})
})
})
describe('Create course list', () =>{
it("Should create a list of courses", () =>{
return request(app).post('/course').send({"id":3,"title":"Première course"}).then((res) => {
res.status.should.be.eq(200)
const listCourses = res.body
const lastCourse = res.body[1]
listCourses.should.be.a('array')
lastCourse.id.should.be.eq(3)
lastCourse.title.should.be.eq("Première course")
listCourses[listCourses.length - 1].should.be.eq(lastCourse)
}).catch((err) => {
throw new Error(err)
})
})
})
describe('Get course list', ()=>{
it("Should get a list of all courses", ()=>{
return request(app).get('/course')
.then((res) => {
res.body.should.have.lengthOf(1)
}).catch((err) =>{
console.log(err)
throw new Error(err);
})
})
})
})
My problem is that when I launch my test I have an error :
TypeError: Cannot read property 'splice' of undefined
I think the problem is in CoursesFixture.js and surely a syntax error somewhere but I can't find where it is.
const { courseList } = require('./courses') should be const courseList = require('./courses')?

firebase set failed first argument contains undefined in property

When I create an event, I do this:
export const eventCreate = ({ title, time, location }) => {
const newPostKey = firebase.database().ref('/events').push().key;
const update = {};
const postDetails = {
eventId: newPostKey,
title,
...
goingNumber: 1,
...
};
update[`/events/${newPostKey}`] = postDetails;
return (dispatch) => {
firebase.database().ref()
.update(update)
.then(() => {
dispatch({ type: EVENT_CREATE });
})
.then(() => newPostKey);
};
};
in the database:
later when I try to update the goingNumber:
export const eventSave = ({ goingNumber, eventId }) => {
return (dispatch) => {
firebase.database().ref(`/events/${eventId}`)
.set({ goingNumber })
.then(() => {
dispatch({ type: EVENT_SAVE_SUCCESS });
});
};
};
I get this error saying:
You're not passing in a value for goingNumber. My guess is that you're looking for
firebase.database().ref(`/events/${eventId}`)
.child('goingNumber').set(goingNumber )