Using async/await JS functionality with 'cchipPrintLoop'

The functionality described in this article can only be used with pdfChip versions 2.6.092 and higher, which have an updated WebKit HTLM rendering engine.

The simplest idea of cchipPrintLoop() is to be a simple loop to modify and print document multiple times:

function cchipPrintLoop() {
   for (d of data) {
       setData(d);
       cchip.printPages();
    }
}
Click to copy

Unfortunately, the page might not be ready for printing just after the setData call (e.g. images not loaded, layout not fully updated, etc.).

So we need to wait until the page is ready for printing by passing a callback to cchip.onPrintReady.
This works, but the simple loop is gone:

function cchipPrintLoop() {
	printNext(0);
}

function printNext(i) {
	if(i > 0)
        cchip.printPages();
        
    if(i < data.length) {
		setData(data[i]);
        cchip.onPrintReady(() => printNext(i+1));
    }
}
Click to copy

A simple loop turns into a kind of "async recursion", making it harder to tell what's going on at first glance.

Modern async/await syntax allows much simpler control flow:

async function cchipPrintLoop() {
    for (d of data) {
        setData(d);
        await new Promise(cchip.onPrintReady);
        cchip.printPages();
    }
}
Click to copy

Now we have a simple for-loop again, but with an additional async keyword and an await new Promise(...) code line.

 

For convenience, pdfChip 2.6.094 or higher introduces a new built-in function for promise creation: cchip.printReadyPromise, which is defined as follows:

cchip.printReadyPromise = () => new Promise( cchip.onPrintReady );
Click to copy

With the help of cchip.printReadyPromise, the print loop becomes slightly simpler:

async function cchipPrintLoop() {
    for (d of data) {
        setData(d);
        await cchip.printReadyPromise();
        cchip.printPages();
    }
}
Click to copy

Example: A more complex scenario 

Here’s a sample with callbacks and complex control flow (including 2 callbacks and an extra argument in the setData function): 

function setData(d, printNextCallback) {
    var [barcodeElement, minh] = setBarcode(d);
    
    cchip.onPrintReady( () => {
        setupPage(barcodeElement, d, minh);
        cchip.onPrintReady( printNextCallback );
    })
}

function printNext(i) {
	if(i > 0)
        cchip.printPages(1);
        if(i < data.length)
	setData(data[i], () => printNext(i+1) );
    
function cchipPrintLoop() {
	printNext(0);
}
Click to copy

Code with async, simple linear control flow (no callback, no extra argument, but extra ‘async/await' keywords): 

async function setData(d) {
    var [barcodeElement, minh] = setBarcode(d);    
    await printReady();
	setupPage(barcodeElement, d, minh);
}

async function cchipPrintLoop() {
	 for (let d of data) {
        await setData(d);
        await cchip.printReadyPromise();
        cchip.printPages();
	}
}
Click to copy

Note: While async/await code is simpler and easier to manage, it does require a deeper understanding of JavaScript to avoid potential mistakes.