Coroutines in Unity – Encapsulating with Promises [Part 2]

Facebooktwittergoogle_plusredditpinterestlinkedinmail

In the last article we focused on the internals behind Unity’s Coroutines and went in depth on how they work. We covered IEnumerator interface and iterator blocks to get a grasp on how the engine takes care of the coroutine functions. We’ve also managed to list a few problems with the implementation and shortcomings that you can stumble upon if a need to write more complex coroutines arises.
In today’s article, we’re going to present you the idea of Promises and where they originated from.

Callbacks

Most asynchronous operations in Javascript APIs return a result with a callback (in C# terms: an Action delegate) when they finish work. You can explicitly provide a function for those, but to follow asynchronous code easier many decide to implement callbacks using anonymous functions. In theory it does seem like a decent upgrade to our Coroutines. Let’s try to form an example of how to do that in C#:

Not bad! As you can see that actually works fairly well. It gives us a possibility to return a value as well as raise errors and react to them. The problem, however, is the code growing horizontally with more indents as you stack coroutines in a sequence. Also, the error checking has to be done in each and every one of them. Eventually, with more complicated functions you end up in a callback hell. What is that? Well, let’s just copy our coroutine calls and stack four of these bad boys:

Just look at the pyramid shape and all the } and })); at the end. Yikes! You’d also need to get really creative with the names as they have to be unique. In terms of errors, you could probably clean it up a bit if you moved error handling to another function. But it still doesn’t look appealing and here we only have four coroutines stacked. When writing more complex functions or perhaps APIs for your backend services, that number can increase drastically. So, what’s the solution?

Promises

Promises have been popularized by many 3rd party Javascript libraries before getting a native implementation in ES6. It’s interesting to note that the idea itself had been actually researched and introduced in the 70s and 80s. Promises as we know them today were first introduced in a year 1988 by Barbara Liskov and Liuba Shira, but a similar idea came from the functional programming languages years before.

A C# library conforming the Promises/A+ Spec was released a couple of years ago and is a big game changer for managing asynchronous operations. Let’s dive into the code.

A Promise is an object that you return from your asynchronous function immediately, so the caller can await resolution (or error) of your operations. Essentially, it represents a proxy for a value not necessarily known when the promise is created. A Promise can be later resolved or rejected once you complete your actions. This allows asynchronous methods to return values and run like synchronous methods: except instead of the final value, they return a promise of having a value at some point in the future. The best part, however, is the simplicity of stacking them with a simple interface. Here’s how we can redo our first example and implement Promises instead of pure Action delegates:

Much better on the caller side! You get to hide and encapsulate coroutine behavior while getting all the advantages from the promises. With .Then() function you can easily stack new promises in a logical order and handle different result types throughout them. Moreover, with .Catch() you can catch exceptions in all of your promises. If any of the above gets rejected, then the promise chain will get immediately terminated and the code will jump to the nearest catch. Not only that, the catch function actually uses Exception type, so you can also easily throw your own exceptions:

As long as you extend from Exception class you can write your own exceptions, mimicking try…catch behavior. Handle them like this:

Summary

As you can see, Promises provide a great mechanism to handle your asynchronous operations. You can easily throw errors from any of your promises in stack, handle returning values as well as hide the coroutine implementation if you use it while working with Unity. You retain all the powerful aspects of Coroutines in terms of the implementation, but also improve greatly the interface for your complicated APIs and services. The library offers much more than what was covered and we strongly recommend looking up the documentation to see what else it has to offer.
In the final part of the series, we’ll show you a real example of writing a REST API interface using Unity’s Coroutines & Promises to achieve the cleanest code possible.

Continued in Part 3 here.

2 thoughts on “Coroutines in Unity – Encapsulating with Promises [Part 2]

  1. Shrikky says:

    Good stuff, a small suggestion.

    Please rename foo to ErrorCode or what-ever that value means, it will make the use case more relevant and faster to understand.

    Yes I know foo bar is the base of all snippets, but this example already demonstrates a brilliant use case which is more than a snippet, hence it will be easier for us to understand the usage faster 🙂

Leave a Reply

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