Estoy usando node html-pdf para generar un pdf y nodemailer para enviar automáticamente un correo electrónico que contiene el pdf cada minuto usando node-cron como se muestra en el siguiente código:
cron.schedule('* * * * *', () => { // function to generate scan report using html-pdf report.getScanReport(); // e-mail message options let mailOptions = { from: {{some_email}}, to: {{some_email}}, subject: 'Testing', text: 'See PDF attachment', attachments: [{ filename:'test.pdf', path: 'C:/Users/test.pdf', contentType: 'application/pdf' }] }; // Send e-mail transporter.sendMail(mailOptions, function(error, info) { if (error) { console.log(error); } else { console.log('Email sent: ' + info.response); } }); }) El problema es que generar el pdf toma ~10 segundos más o menos, por lo que el programa intenta enviar el correo electrónico antes de que exista el archivo pdf generado y luego aparece el error: Error: ENOENT: no such file or directory
Como referencia, aquí se muestra cómo funciona la función getScanReport() :
const getScanReport = () => { Promise.all([ pool.query(query1), pool.query(query2) ]).then(function([results1, results,]) { var obj1 = results1.rows; var obj2 = results2.rows; ejs.renderFile('./views/pages/scanreport.ejs', {scanObj: scanObj, woObj: woObj}, (err, data) => { if (err) { console.log(err); } else { let options = { "height": "11.25in", "width": "8.5in", "header": { "height": "20mm" }, "footer": { "height": "20mm", }, }; let filename = "test.pdf"; pdf.create(data).toFile(filename, function (err, data) { let fileloc = 'C:/Users/' + filename; if (err) { console.log(err); } else { console.log("Successfully created pdf"); } }) } }); }); }¿Hay alguna manera de asegurarse de que se genere el pdf antes de intentar enviar el correo electrónico?
Suponiendo que puede modificar su función getScanReport, use una Promesa . Luego, en su función de correo electrónico, use async / await para esperar esa promesa.
(Puede hacer clic en los enlaces para leer más sobre cómo funcionan las promesas y async/await si no las usa con mucha frecuencia).
Por ejemplo (editado desde que la publicación ahora incluye el funcionamiento interno de getScanReport):
report.getScanReport = () => new Promise( //announcePDFReady() is a function we call to resolve our promise announcePDFReady => { Promise. all( [ /* ... */ ] ). then( function( [ results1, results2 ] ) { /* ... */ renderFile( /* ... */ ( err, data ) => { /* ... */ pdf.create( data ).toFile( filename, ( err, data ) => { let fileloc = 'C:/Users/' + filename; if (err) { console.log(err); } else { console.log("Successfully created pdf"); //announce ready right here! announcePDFReady( data ); } } ) } ) } ) } ); //... //we write 'async' before the cron job function definition async () => { //this is inside the cron job function const pdfIsReady = await report.getScanReport(); //since report.getScanReport() returns a promise, //'await' here means our code will stop until the promise resolves. if( pdfIsReady === false ) { //it failed. Do something? Ignore it? } else { //pdf is ready. We can send the email //etc. } }Suponiendo que está usando este paquete NPM: https://www.npmjs.com/package/html-pdf-node , puede usar las promesas que proporciona para hacer algo después de la creación del archivo PDF.
Puede ver que crea un PDF y luego ejecuta código adicional. Lo he editado un poco para que sea más fácil de entender.
html_to_pdf.generatePdf(file, options).then(() => { // this code will execute after the PDF has been generated. });Si está utilizando un paquete diferente, ¿puede vincularlo? Gracias.