Last time, we converted the C# version of the PDF Document sample program so that it saved the pages to disk as image files. Today we’ll port those changes to JavaScript with Promises.
function viewPage() {
WinJS.log && WinJS.log("", "sample", "status");
var pageNumber = parseInt(pageNumberBox.value, 10);
if (isNaN(pageNumber) || (pageNumber < 1) ||
(pageNumber > pdfDocument.pageCount)) {
WinJS.log && WinJS.log("Invalid page number.", "sample", "error");
return;
}
output.src = "";
progressControl.style.display = "block";
// Convert from 1-based page number to 0-based page index.
var pageIndex = pageNumber - 1;
var page = pdfDocument.getPage(pageIndex);
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.fileTypeChoices["PNG image"] = [".png"];
picker.pickSaveFileAsync().then(outfile => {
if (outfile) {
outfile.openTransactedWriteAsync().then(transaction => {
var options = new PdfPageRenderOptions();
options.destinationHeight = page.size.height * 2;
options.destinationWidth = page.size.width * 2;
page.renderToStreamAsync(transaction.stream, options).then(() => {
transaction.close();
});
});
}
}).done(() => {
page.close();
// Delete the code that sets the blob into the image
progressControl.style.display = "none";
});
}
This is an uninspired direct translation of the C# code to JavaScript. We can imbue it with a little JavaScript inspiration by flattening the promise chain a bit.
var transaction;
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.fileTypeChoices["PNG image"] = [".png"];
picker.pickSaveFileAsync().then(outfile => {
if (outfile) {
return outfile.openTransactedWriteAsync();
}
}).then(trans => {
transaction = trans;
if (transaction) {
var options = new PdfPageRenderOptions();
options.destinationHeight = page.size.height * 2;
options.destinationWidth = page.size.width * 2;
return page.renderToStreamAsync(transaction.stream, options);
}
}).then(() => {
transaction && transaction.close();
}).done(() => {
page.close();
// Delete the code that sets the blob into the image
progressControl.style.display = "none";
});
Instead of nesting the promises, I chained them, and each step of the chain checks whether the previous step succeeded before proceeding. (If not, then that step does nothing.)
Alternatively, I could’ve thrown the Promise into an error state, but WinRT tries to reserve exceptions for unrecoverable errors, primarily out-of-memory conditions for a small allocation, or a programmer error. Errors that a program is expected to recover from are generally reported by an in-API mechanism. (There are notable exceptions to this principle, primarily in the I/O area.)
Anyway, you may have noticed that I used arrow functions, which are feature of ES6. Next time, I’m going to take it even further.
0 comments