Using PromiseKit

      6 Comments on Using PromiseKit

PromiseKit is a framework that will simplify working with async code and make your code very elegant and simple to follow. Learn how to use it in this post.Working in swift (and ObjC) you should be comfortable working with async code. Sooner or later you’ll run into a problem called ‘callback hell’ where in the completion handler of one method you’re doing another async call. And in the completion handler of that async method you call another, and so on… ‘Callback hell’ makes your code hard to follow and less elegant. PromiseKit is a framework that will simplify working with async code and make your code very elegant and simple to follow. This pattern is not specific for PromiseKit, in fact, promises can be found in many languages. In one of the previous articles we used promises in JavaScript when we talked about Firebase Cloud Functions. PromiseKit is a swift implementation of the promises. In this article we’ll go over some most common examples and get you started with PromiseKit.

Promises

Promises are wrappers around your async tasks. They can succeed or fail. Instead of using closures in your functions, your functions simply return a ‘Promise’ object. Take a look at the example of a function before and after using PromiseKit:

You can notice the difference in readability already. The power of promises is that they can be chained. We’ll talk about that in a bit.

Guarantees

A ‘Promise’ can be rejected, but a ‘Guarantee’ always succeeds. That is the main difference between them. A good example of a ‘Guarantee’ are animations. Guarantees were introduced in PromiseKit 5 in order for you to be able to write code without writing the error handling logic.

Promise Chain

Promises are linked into a chain, and this makes your code incredibly readable. You also won’t get  the ‘Callback hell’ that you might encounter in your standard async code. This is how a typical promise chain looks like:

You start your chain with the ‘firstly’ block. In this block you execute a function that returns a ‘Promise’. ‘firstly’ is just syntactic sugar and you can easily call the function directly. When the first block is finished executing and the ‘Promise’ is resolved, the next block in the chain gets executed. In our case it’s the ‘then’ block. In this block you have access to the resolved value of the previous block. The promise was using a ‘String’ as a type parameter so the value that will be passed to the ‘then’ block will be a string. Notice how this value is not an optional. The ‘then’ block will take in values from the previous ‘Promise’ and will return another ‘Promise’. You can see how we can easily chain a lot of promises together.

‘done’ block is similar to the ‘then’ block. The only difference is that the ‘done’ block is not returning a promise. This is supposed to be the end of the chain. All the errors are handled in the ‘catch’ block. If any of the blocks in the chain failed. To be precise, if any of the promises got rejected. All the subsequent blocks would be skipped and the ‘catch’ block would be called. In our code example we’ll see that there’s one type of block that always executes, the ‘ensure’ block. More on that later.

These are the basics of PromiseKit. Next we’ll implement a simple app where you’ll learn how to use this in practice.

An Example

We’ll build a simple app that will connect to unsplash.com, fetch a random photo, parse the meta-data and display the photo on the screen. This is a common scenario you’ll find in a lot of apps and we’ll see how simple it is to do it using PromiseKit.

Project Prep

Let’s quickly go over some assumptions. Obviously, you’ll need your API key to connect to unsplash. You can register for a free dev account on unspash.com. We’ll only be using the endpoint for getting random photos.

To keep this article focused on PromiseKit I won’t be going through some utility classes; like, parsing the response from the server into objects. I’ll assume you know how to do that. You can always checkout the example project and look through that code. So, let’s start making promises 🙂

Making Promises

In the simple example above, we had a function that was returning a ‘Promise’ object. We’ll create two functions. One will make an API call and return image metadata. The other one will return the actual image data.

Fetch and Parse

The first function is a very common pattern in iOS development, fetch and parse data. Let’s check it out:

In the guard statement you can see that we’re returning a promise that rejects with an error. We can define our custom errors here, like we usually would. If this promise was ever returned, our promise chain would stop executing and the ‘catch’ block in the chain would be executed.

PromiseKit has a lot of extensions for most of the UIKit and Foundation. For example, URLSession has an extension where you can wrap your standard data task into a promise. The wrapped data task will be resumed automatically. When the task completes, the results will be passed in to the next block. Which in our case is the ‘compactMap’.

A thing to note is that we’re executing our ‘compactMap’ block in the background. You can set the execution queue on most blocks in PromiseKit.

This ‘compactMap’ block is similar to the ‘compactMap’ that you’re used to. This block can return an optional. If your object is nil, the block will emit an error and your chain will break. If your object is not nil, it will be wrapped in a promise and returned to the next block. The error that this block returns will be a generic PromiseKit error. If you want to return your custom error you can easily do so. Just return a promise that rejects with your custom error, like we did a couple of lines above.

We also have ‘map’ at our disposal and it’s doing exactly what you would expect 🙂

Download Data

The second function that we’ll cover is also one that’s commonly found in iOS development. Downloading large files. This is a fairly simple function. So we’ll use the opportunity to demonstrate how to pass multiple values out from our function:

We’re passing the ‘Image’ object to the function, but we’re returning a promise that contains a tuple. Tuples are a simple way to return multiple values from your function. You’ll notice that we’re using a convenience function ‘.value(..)’ to create our promise.

Guaranteed Animation

After making some promises, we can make some guarantees. A guarantee is a promise that can’t fail. A good example would be animations. So we’ll create our animations guarantee:

This function will start our activity indicator, disable user interaction on the image view and return an animation guarantee using the UIView extension.

Let’s see how all these bits fit together.

Putting it Together

What we’ll do is start the loading animations, fetch a random photo, get the raw image data, convert the data to UIImage, update the UI, stop the loading animations and display any errors to the user. If you had to code all this without using PromiseKit, you would write quite a few lines of code, but with PromiseKit it’s only a couple of lines of code.

This is the function that’s doing all the work:

If you look at it more closely it’s doing all the steps that we’ve just described and it’s reading nicely from top to bottom. No more callback hell 🙂 A few notes about the function. We’re creating a UIImage in one of the blocks and returning a promise that rejects with a custom error, if the image creation fails. The ‘ensure’ block will always execute, no matter what. This is the perfect place to stop all the loading animations.

Test Run

The image view has a tap gesture recognizer. Every time you tap on the image it will load a new random image. This is the final result:

Hopefully by now you see how easy PromiseKit really is and that you’ll end up using it in your projects.

Conclusion

My first touch with promises was with JavaScript when I was writing the article for Firebase Cloud Functions. I liked how easy and readable async code looked like. Someone recommended to me ages ago to check out PromiseKit, but I never got around to it. I’m glad I finally got the time and shared it with you.

PromiseKit really does make your code more readable. It’s incredibly easy to get used to. You’ll encounter some initial frustrations with Xcode autocomplete and formatting, but once you get past those, you’ll have loads of fun. And like they say, your colleagues will be grateful for the readable code you’ll be writing from now on.

We only covered some basics here, but this should be enough to get you started with PromiseKit. You can learn a lot more on their GitHub repo.

I really hope you’ve enjoyed this article and that you’ve learned something new today. You can find code snippets in the GitLab repo as well as the complete demo project. As usual…

Have a nice day 🙂
~D;

More resources

6 thoughts on “Using PromiseKit

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.