Hi,
Is it possible to get a promise returned when downloading\saving a pdf? I have seen other questions raised from a year ago, but no answers seemed to be offered.
I am using the client side version of the library, does the node version offer this functionality?
Thanks
+1
Promises implemented by commit https://github.com/bpampuch/pdfmake/commit/edcaaecd50e6917ae9f1e93647bbe3a4f5b5d65a in master.
@liborm85 is there any documentation / example that shows to how to call the async/await version of getBuffer ?
@liborm85 is there any documentation / example that shows to how to call the async/await version of getBuffer ?
Here is a basic example. Only applicable to the master branch for the moment (... which is not a stable branch). In the below code, is it assumed that you have pdfmake libs in a build folder at the same level as the file containing the below example.
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title>PDF rendering in an iframe</title>
<script type="text/javascript" src="build/pdfmake.js"></script>
<script type="text/javascript" src="build/vfs_fonts.js"></script>
</head>
<body>
<script type="text/javascript">
var docDefinition = {
content: [
{
text: [
'Test of pdf rendering in an iframe ',
{text: 'using async call.\n\nAPPLICABLE TO MASTER BRANCH.', bold: true},
],
fontSize: 15
}
]
};
function successCallback(dataUrl) {
const targetElement = document.querySelector('#iframeContainer');
const iframe = document.createElement('iframe');
iframe.src = dataUrl;
iframe.width = "800";
iframe.height = "600";
targetElement.appendChild(iframe);
}
function failureCallback(error) {
var div = document.getElementById('iframeContainer');
div.innerHTML += 'Cannot dispaly pdf for the following reason: '+error;
console.error("Operation failed with the following error: " + error);
}
const pdfDocGenerator = pdfMake.createPdf(docDefinition);
const promise = pdfDocGenerator.getDataUrl();
promise.then(successCallback, failureCallback);
</script>
<div id="iframeContainer"></div>
MAKE SURE YOU USE A LIB COMING FROM MASTER BRANCH...
</body>
</html>
Is this out yet?
For anyone who wants to "promisify" the existing API:
async function(docDef) {
const data = pdfMake.createPdf(docDef)
const wait = pdfData => new Promise(resolve => {
pdfData.getBlob(blob => {
zip.file(`${fileNameBase}.pdf`, blob);
resolve();
});
});
await wait(data);
}
@j-funk not sure to understand : I have a case with a downloadable image or a font like in #2066 and because there is some break in returning promises, all errors are not reported.
any help needed to release the 0.2 @liborm85 ?
@wadouk - then just add some error handling to the code in the above example, that code is quick and dirty to assist people experiencing this problem
just to share with some error handling
const pdfDocGenerator = pdfMake.createPdf(docDefinition1)
return new Promise((resolve, reject) => {
function unhandled(e) {
reject(e)
}
setTimeout(() => {
reject(new Error('timeout'))
window.removeEventListener('unhandledrejection', unhandled)
}, 20000)
window.addEventListener('unhandledrejection', unhandled)
pdfDocGenerator.download("der.pdf", () => {
resolve()
})
})
async function(docDef) { const data = pdfMake.createPdf(docDef) const wait = pdfData => new Promise(resolve => { pdfData.getBlob(blob => { zip.file(`${fileNameBase}.pdf`, blob); resolve(); }); }); await wait(data); }
If you want to actually return the value, this worked for me (with getBuffer in my case):
async function(docDef) {
const data = pdfMake.createPdf(docDef)
const wait = pdfData => new Promise(resolve => {
pdfData.getBuffer(buffer => {
resolve(buffer);
});
});
return await wait(data);
}
One problem I had using PDFMake and opening in the same window, was that chrome will not be able to download the PDF because the original window is no longer available. This does not happen in edge or firefox. The solution I came up with (FWIW) is as follows:
const pdfDocGenerator = pdfMake.createPdf(createDocument());
pdfDocGenerator.getDataUrl(function (dataUrl) {
const targetElement = document.getElementById('iframeContainer');
const iframe = document.createElement('iframe');
iframe.src = dataUrl;
iframe.scrolling = "no";
iframe.style = 'position: absolute; width: 100%; top: 0; left: 0; height: 100%; border: none; overflow: hidden; margin: 0; padding: 0';
$('.spinner').removeClass('spinner');
targetElement.appendChild(iframe);
});
Most helpful comment
Is this out yet?
For anyone who wants to "promisify" the existing API: