- We are writing a digital textbook-reading app.
- Most of the time you have a "basic" license for your textbook, but one (and only one) of your computers can request an "enhanced" license.
- You can only print from the computer with the enhanced license.
- We want a simple
printAsync()method that we can attach to our click handler for a print button somewhere in the UI.
- If the user has the basic license, we need to check if it's possible for them to acquire the enhanced license:
- If so, ask the user if they want to upgrade, and then continue the print operation if they agree.
- If not, error out: printing is impossible.
- Printing is an asynchronous operation, provided to us via
window.cPlusPlusApis.print, that could fail (e.g. if the printer is out of paper).
- Due to some horrible threaded C++ code, we get deadlocks if the user navigates through the book at the same time as the book is printing, so we need to block the UI while it prints.
- Use a bunch of promise methods that work together to encapsulate all this complexity into different layers.
- The simplest of the bunch is the
dialogsmodule: it just gives you some nice promise-returning, jQuery-UI-dialog-using versions of
prompt. It exemplifies the use of deferreds to create promise-returning methods, even in situations where the asynchronous nature of the task is indeterminate (i.e. depends on the user clicking a button).
drmmodule talks to the server (via Ajax) to figure out if a user's computer can upgrade to the enhanced license, or to perform the upgrade process itself. It exemplifies a few more advanced promise-consumption techniques.
printingUImodule uses the former two to create a (private) function,
ensureEnhancedAsync, that carries out all the UI and business logic around upgrading to enhanced if at all possible. It exports a
printAsyncfunction, which makes use of
ensureEnhancedAsyncto do its very best to print, or error out to the user if it's not. Here we see the true power of error bubbling and promise piping.
- Finally, some other part of the app will wire up
printAsyncexport to a button somewhere. That's the easy part ;).