jihad.khorfan jihad.khorfan - 1 month ago 15
MySQL Question

synchronous mysql queries in node when creating a pdf

hi i'm trying to write a PDF file using data from MySQL database but when i run the script it give me that i end the PDF file creation and after that i tried to insert data to it ..... i think it's because MySQL in node is Asynchronous . is there any solution for this ?
here is my code ...

var project_ID = 1;
var PDFDocument = require('pdfkit');
$('#pdf').click(function(e) {
e.preventDefault();
var pdf = new PDFDocument;
pdf.pipe(fs.createWriteStream(__dirname + '/../MyFile.pdf'));
var option;
switch ($("input[name=report-type]:checked").val()) {
case 'all-issues':
option = {project_id: project_ID};
break;

case 'all-issues-customer':
option = {project_id: project_ID, customer: customer};
break;
}
connection.getConnection(function (err, conn) { //make connection to DB
if (err) { //error handling
showNotification('error connecting: ' + err.stack, 'danger', 'glyphicon glyphicon-tasks');
return;
}
conn.query('SELECT issues.id, issues.dbid , issues.date, issues.charm , issues.defect ,issues.key , issues.status, issues.summary, issues.description , actions.date as action_date, actions.description as action_desc FROM issues' +
' INNER JOIN actions on issues.id = actions.issue_id WHERE ? ', [option], function (error, data) {
if (error) {
showNotification('Error :' + error, 'danger', 'glyphicon glyphicon-tasks');
} else {
var lastID = -1;
data.forEach(function (data) {
if (lastID !== data.id) {
lastID = data.id;
pdf.addPage();
pdf.text('Number :' + data.dbid).moveDown();
pdf.text('Customers : ');
pdf.text('Baseline : ');
pdf.text('Error/Wish : ' + data.key).moveDown();
pdf.text('Charm : ' + data.charm + ' / Defect : ' + data.defect + ' Status : ' + data.status);
pdf.text('Summary : ' + data.summary);
pdf.text('Description : ' + data.description).moveDown();
pdf.text('Actions/ History :').moveDown();
}
pdf.text(' - date : ' + convertDate(data.date));
pdf.text(' description : ' + data.description).moveDown();
})
}
});
conn.release();
});
pdf.end();
});

Answer

It is because of the asynchronous nature of Node.js. You can quickly alter your code in a few areas to fix it though. You have some calls like conn.release() and pdf.end() that fall outside of the your callback.

In the code below I've moved conn.release() and pdf.end() to the last lines of your mysql connection callback.

var project_ID = 1;
var PDFDocument = require('pdfkit');
$('#pdf').click(function(e) {
    e.preventDefault();
    var pdf = new PDFDocument;
    pdf.pipe(fs.createWriteStream(__dirname + '/../MyFile.pdf'));
    var option;
    switch ($("input[name=report-type]:checked").val()) {
        case 'all-issues':
            option = {project_id: project_ID};
            break;

        case  'all-issues-customer':
            option = {project_id: project_ID, customer: customer};
            break;
    }
    connection.getConnection(function (err, conn) { //make connection to DB
        if (err) { //error handling
            showNotification('error connecting: ' + err.stack, 'danger', 'glyphicon glyphicon-tasks');
            return;
        }
        conn.query('SELECT issues.id, issues.dbid , issues.date, issues.charm , issues.defect ,issues.key , issues.status, issues.summary, issues.description , actions.date as action_date, actions.description as action_desc FROM issues' +
            ' INNER JOIN actions on issues.id = actions.issue_id WHERE ? ', [option], function (error, data) {
            if (error) {
                showNotification('Error :' + error, 'danger', 'glyphicon glyphicon-tasks');
            } else {
                var lastID = -1;
                data.forEach(function (data) {
                    if (lastID !== data.id) {
                        lastID = data.id;
                        pdf.addPage();
                        pdf.text('Number :' + data.dbid).moveDown();
                        pdf.text('Customers :            ');
                        pdf.text('Baseline :            ');
                        pdf.text('Error/Wish :            ' + data.key).moveDown();
                        pdf.text('Charm :  ' + data.charm + ' / Defect :  ' + data.defect + '                   Status : ' + data.status);
                        pdf.text('Summary :                ' + data.summary);
                        pdf.text('Description :            ' + data.description).moveDown();
                        pdf.text('Actions/ History :').moveDown();
                    }
                    pdf.text('          - date        : ' + convertDate(data.date));
                    pdf.text('            description : ' + data.description).moveDown();
                })
            }
            conn.release();
            pdf.end();
        });
    });
});

That should ensure that those calls aren't made until after the callback logic is done. Note that if you had a callback (or more) within that callback you often times have to make sure those functions are called inside of those callbacks. You'll find yourself in the middle of Callback Hell quite often.

Best of luck to you!