Closures, Promises, and Asynchronous Programming in Swift, explained yet again

Here’s my take at closures and promises in Swift!


If you’ve used Swift for any decent amount of time, you have probably came across closures at one point or another. But how do they work? Let’s dive in.

Closures: “An input and an output”

Think of a closure like a machine: there’s an input and an output. To declare a closure, you declare the input types and the output types, separated by an arrow:

Closures also include a body: the part that takes the input and processes it into an output. Begin the body with an opening brace ({), and name the input types, followed by the word in:

To return the output, just use return like in a function:

If you want a closure that doesn’t have an input or output, just use an empty tuple:

Getting the output from closures

It’s pretty simple to get the output from a closure. Since the closure’s output is the callback’s body’s input, you can use the in syntax we learned above:

Why are closures useful?

Closures allow you to store code in an object. For example, below the equivalent closure is created from the function sayHelloFunction and then passed as a parameter in another function:

Because the exclaim function takes any closure that inputs and outputs a single String, you could create a new closure on the fly and pass it to the function:

You could also directly pass a closure as a parameter:

All of these methods are super helpful for dealing with asynchronous operations. (An asynchronous operation is one that takes some time to load, so the computer doesn’t wait for it and just gets back to it when it finishes.) For example, Grand Central Dispatch takes a closure as a parameter and waits for the specified delay to time out before executing it. If it wasn’t asynchronous, then the whole program would lock up and become unresponsive until the code passed to GCD completed. By using a closure, we tell GCD what to execute when it is done:

Why does the “Done” print second, even though it was written first? Because it’s in a closure, the computer skips over it until it’s done (in this case, until the 10-second deadline is reached) before executing the body of the closure. Since the second print statement is not inside a closure, it is immediately available for execution, so the computer executes it immediately, resulting in “Will I print first or second?” being printed first.

Now we can use closures to ensure that our code runs in order, despite the wait time of a long-running function:

The label won’t update until the data is returned from the API!

Pyramid of Doom

If you look at the example above, you’ll quickly realize how difficult your code will become to manage once you start having multiple closures, like this:

This code is called a Pyramid of Doom. Ugh, what a mess! And don’t even think about trying to implement proper error handling. There must be a better way…

Better ways to deal with asynchronous programming

PromiseKit

Thankfully, the wonderful creators of PromiseKit have fixed the Pyramid of Doom. To execute asynchronous tasks in order, you just use the then function provided by PromiseKit, similar to other programming languages like JavaScript:

Ahh, that’s much better!

AwaitKit

AwaitKit takes this a step further by abstracting the promises, too. It allows you to write asynchronous code as though it were synchronous! To use it, create an async block, then put await followed by the promise:

Woah! Everything was both written and executed in order, with minimal code. If you’d like to learn about the magic behind AwaitKit (it uses GCD Semaphores), you can read about it here and here.

Conclusion

Closures work like a machine and allow you to store code in an object, accepting an input and giving an output when it is called. They are super useful when you need another function to execute your code (such as GCD), which makes them particularly useful in asynchronous programming.

Asynchronous programming may be difficult to grasp at first, but you can think of it as the computer not waiting for the task to finish, and instead coming back to it later once it’s done. Unfortunately, using closures with asynchronous operations can result in the Pyramid of Doom, where multiple closures are passed into each other, but this can be solved in part by using awesome libraries like PromiseKit and AwaitKit.


I hope you found this guide a good read, and you’re a little more comfortable with using the things I mentioned! If you’re interested in my work, keep scrolling for more stories. Good luck with your next project, and have a wonderful day!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s