Reputation: 33
am using await inside await, first i have used await in line 'a', it works fine and enters inside continues to execute from line 'b' to line 'd', but after that it needs to go inside that query and has to execute from line 'e' to line 'f', then it has to execute line 'g' and 'h' finally and return result but problem is after line 'd' it will not execute inside code instead it comes to line 'g' and executes further code and then comes back to line 'e' which causes error. Please help me out.
var writeStreamData = '';
var surveyBlockId = req.body.surveyBlockId;
var title = req.body.title;
a. await SurveyAnswer.find({'blockId': surveyBlockId}, (err, doc) => {
b. if(doc.length!=0){
userName = '';
userIdList = Object.values(doc.reduce((acc,cur)=>Object.assign(acc,{[cur.userId.toString()]:cur}),{}));
const pdfDoc = new PDFDocument({margin: 50});
writeStreamData = pdfDoc.pipe(fs.createWriteStream('pdf_files/SurveyAnsweredUserList.pdf'));
pdfDoc.fontSize(25).text('Home Owners Association', {align: "center"});
pdfDoc.lineCap('butt').moveTo(30,80).lineTo(600,80).stroke();
pdfDoc.moveDown();
pdfDoc.fontSize(20).text('Survey Title : '+title);
pdfDoc.moveDown();
pdfDoc.fontSize(20).text('List of Users');
if(doc.userIdList!=0){
var counter = 0;
c. userIdList.forEach(async element => {
userId = element.userId.toString();
d. await User.findOne({'_id':userId},async(err1, doc1) => {
e. if(!err1){
counter++;
userName = doc1.firstname + " "+ doc1.lastname;
pdfDoc.fontSize(15).text((counter)+". "+userName).moveDown();
}else{
counter++;
//return eachCb(err1)
}
//eachCb();
})
}, function(err, data) {
if(err){
response = {
"message": "failed"
}
res.send(response);
}
});
}else{
pdfDoc.fontSize(15).text('No User answered');
}
f. pdfDoc.end();
}else{
response = {
"message": "failed"
}
res.send(response);
}
});
g. fs.readFile(writeStreamData.path, function(err, data) {
h. if(err) throw err;
const pdf = data.toString('base64');
response = {
"message": "success",
"data": pdf
}
res.send(response);
})
});```
Upvotes: 0
Views: 1736
Reputation: 451
You can make use of Promise inside Promise instead of async await to get your work done. I have an example similar to yours which i am using to fetch data from s3 bucket. You can take reference to implement promise inside promise.
new Promise((lresolve) => {
s3.listObjectsV2(params, (err, devicedata) => {
if (!err) {
const data = devicedata.CommonPrefixes;
data.forEach(value => {
const prefix = value.Prefix.replace(params.Prefix, '').replace('/', '');
devices.push(prefix);
});
lresolve(devices);
}
});
}).then(qDevices => {
const devicePromise = [];
qDevices.forEach(devicepath => {
devicePromise.push(
new Promise((qresolve) => {
params.Prefix = `${staticPrefix + devicepath}/tyre/`;
let processedData = [];
s3.listObjectsV2(params, (err, data) => {
if (!err) {
const contents = data.Contents;
const fetch = [];
contents.forEach(content => {
fetch.push(getObject(content))
});
Promise.all(fetch).then(data => {
data.forEach(d => {
processedData = processedData.concat(d);
});
qresolve(processedData);
});
}
});
}));
});
Upvotes: 0
Reputation: 2296
In my opinion the cleanest way is to write wrappers for functions like fs.readFile
that return a promise instead of using a callback. This makes it easier to compose everything with await
.
You can use bluebird to automate this conversion as shown in this answer: https://stackoverflow.com/a/34642827/303637
Upvotes: 0
Reputation: 2679
You are doing a few things wrong. You can only await
a promise. SurveyAnswer.find()
receives a callback function, it doesn't return a promise. So, you can't await it. Same goes for d and g. As you are using callback style so await
in front of a, d and g is useless.
Also, await
does not work in forEach
function. Use for...of
instead.
Upvotes: 1