There’s a certain tedium in implementing asynchronous operations using the typical patterns common in apps. Typically every call requires a completion handler that either handles the result or handles an error.
I’ve taken a look at PromiseKit 3.0.0 as a potential means to reduce some of that effort due to the following advantages
- escape from callback hells
- treat async values almost like synchronous values
- reduce cognitive overhead in implementing async operations
The essence of promises is that they turn asynchronous operations into function-like entities. The return value is obtained by
thening a promise. The following code shows the definition of a promise based on a typical async operation and how the result from that async operation is obtained from the promise.
As an important note, the async code is executed at the time the Promise function is called. Therefore, the result could be retrieved by
thening the Promise when it is needed. In PromiseKit, there is even a
when to allow actions to be taken as soon as the result is ready.
Instead of descending into a callback chain to perform multiple dependent operations, a Promise chain can be created in a function compositional way. The result of each Promise in this example is passed on to be ingested by the next Promise.
WARNING: The documentation at promisekit.org may refer to
.catch. This has been replaced by
.errorin Swift. Every place that you see
.errorshould be used instead.
The Swift generic definition of a Promise as
Promise<T> provides for a clear way of documenting return types such as
Promise<String> directly within code.
Chaining async calls with completion handlers
A corresponding callback hell, I mean chain, would look something like
Really, it’s the error handling that explodes the callback chain. PromiseKit abstracts that error handling mess away into a single
PromiseKit may seem like a solution without a problem since you can get to the same end result without it. It could be a solution if you consider meaningful, readable code to be a problem worth solving.
The abstraction benefits that using the Promise type provides makes sense to me. It allows for keeping the logically related components of asynchronous operations together instead of split apart as with the callback form. A flat
then chain is immediately preferable to a nested callback hell.
In Swift, the implementation of promises by PromiseKit is elegant in how it integrates with the language. The benefits are visibly apparent within my simple examples.
Aesthetics are not the only benefit. I also look forward to the effort that can be saved from not having to trace through compound callback mires during development and maintenance of my code.
My conclusion is that promises can bring clarity to the handling of asynchronous operations in Swift in a way that improves our ability to create great user experiences in apps.