Is there a way to get a callback after everything asynchronous is finished and the file is completely stored to the file system?
I can't find a way. Probably I am missing something?
My workaround (I PDFkit should provide a callback method or promise):
Store the writeStream in a extra variable and watch it for a change:
doc = new PDFDocument();
writeStream = fs.createWriteStream('filename.pdf');
doc.pipe(writeStream);
doc.end()
writeStream.on('finish', function () {
// do stuff with the PDF file
});
Yeah the finish event is how I would have done it. I suppose we could add a callback as a convenience. Do you think it's worth it given that the finish event is already there?
I see two ways of doing it:
doc.end() to show people the easy way to wait for the finished document (so they do not have to search as long as I did :)).+1 for "finish callback".. this will be much more "intuitive"
+1 for callback
The problem with adding a callback to the end method is that PDFKit doesn't actually know when all of the data has been flushed to whatever stream you're writing to (file, http response, etc.). Since PDFKit has no access to the actual writable stream it is being piped to (PDFKit itself is a readable stream, and you set up the writable part), it only knows when it has finished pumping out chunks to whoever might be reading. It may be some time later that the writable stream actually flushes its internal buffers out to the actual destination. So, we could add a callback to the end method, but it might get called before the stream is actually done writing. This could cause subtle and hard to debug race conditions in people's code who assume that everything is really done when that callback is called.
For this reason, my vote is to keep PDFKit the way it is now and not to add a callback to doc.end. It's not too hard to add a finish event handler to the stream you set up to pipe to if you need that, and it will prevent future headaches.
I think it would be a great idea to document this then.
I had to search a lot to find this. Probably somewhere near the doc.end documentation.
On August 21, 2014 at 22:06:13, Alex Naspo ([email protected]) wrote:
+1 for callback
—
Reply to this email directly or view it on GitHub.
+1 for callback
+1
+1
Thanks a lot. I was facing weird error in my execution.
When executing multiple queries it was working proper and when running single query then pdf was not created properly.
Then realised this callback issue was there.
Thanks a lot for finish callback.
I believe it's not quite as simple as listening for the 'finish' event on the write stream, _specifically in the case of errors_, so I implemented the following function which returns a Promise.
function savePdfToFile(pdf : PDFKit.PDFDocument, fileName : string) : Promise<void> {
return new Promise<void>((resolve, reject) => {
// To determine when the PDF has finished being written successfully
// we need to confirm the following 2 conditions:
//
// 1. The write stream has been closed
// 2. PDFDocument.end() was called syncronously without an error being thrown
let pendingStepCount = 2;
const stepFinished = () => {
if (--pendingStepCount == 0) {
resolve();
}
};
const writeStream = fs.createWriteStream(fileName);
writeStream.on('close', stepFinished);
pdf.pipe(writeStream);
pdf.end();
stepFinished();
});
}
Instead of calling .end() directly, you call this function and pass the pdf document and filename.
This should correctly handle the following situations:
That's a nice solution. :) It would be great to see that in the library itself so that users don't have to deal with these issues.
+1 for _at least_ a note in the doc.
+1 it is elementary
I had a similar issue where I need to save the file to s3.
writeStream.on('finish', () => { /* s3 upload code here */ })
Worked great, thanks @spieglio.
I had a similar issue where I need to save the file to s3.
writeStream.on('finish', () => { /* s3 upload code here */ })Worked great, thanks @spieglio.
@SeanCannon
can you share your s3 pdf create code?
Because sometimes i can creating pdfFile successfully with AWS lambda. But sometimes pdf file created right(pdf file size is right) while but has a error so cant open file, or sometimes pdf file created wrong(file size is look 16).
I cant handle this situation.
If anyone has trouble catching the error when a file has failed to upload, following code can be added to the function of codeandcats
writeStream.on("error", (e: Error) => {
reject(e);
});
This solved it for me:
```
const stream = fs.createWriteStream(localFilePath);
doc.pipe(stream);
.....
doc.end();
await new Promise<void>(resolve => {
stream.on("finish", function() {
resolve();
});
});
```
It's a bit less verbose.. just waits before continuing.
Most helpful comment
My workaround (I PDFkit should provide a callback method or promise):
Store the writeStream in a extra variable and watch it for a change: