Quick Examples

Example: Show Me.

In the above recipe, func1 will be called first. Then the result of func1 will be passed to func3andfunc5 in parallel. func4 will be called after func3 has finished and will be passed the result of func3. Likewise, func6 will be called after func5 has finished and will be passed the result of func5. When bothfunc4 and func6 have finished, their results will be combined into a tuple and passed to func7. If any of the functions throws or asynchronously responds with an Error, then errorHandlingFunc will be invoked with the error as an argument.

In the above recipe we see six of HoneyBee’s supported function signatures. func1 is an Objective-C style errorring async callback. func2 is a synchronous Swift throwing function. func3 completes with an optional error but does not generate a new value. HoneyBee forwards the inbound value automatically. func4 is a Swift style, generic enum-based result which may contain a value or may contain an error. func5 is asynchronous but cannot error (UI animations fit this category). And successFunc is a simply, synchronous non-errorring function.

HoneyBee supports 34 distinct function signatures.

Example: Safe By Default

One of the many problems with the pyramid of doom is that error handling is hard to get right.

Not very pretty, right? And there’s still issues here. This form of processImageData has made its contract correctness dependent on the contract correctness of all of the invoked asynchronous methods. What happens if one of the methods fails to call its completion? Or calls back more than once? What happens if a method calls the completion, but with two nil values? HoneyBee handles each of these issues for you, so that your method’s correctness is not dependent on the correctness of any dependency method.
Let’s take a look at the Honeybee form:

So much cleaner right? And Bonus Points, the HoneyBee implementation allows us to parallelize the first two async calls to loadWebResource, so this form has better performance than the others too. Groovy.

(If you’re wondering about the =<< operator it’s pronounced bind. It performs a partial function application, binding the argument to the function. See the API docs for more details.)

Error Diagnostics

Diagnosing problems in misbehaving concurrent code is really hard right? Not with HoneyBee. Consider the following:

HoneyBee pinpoints the file and line where the recipe errored, along with the path which was taken to arrive at that function, and the inbound subject value. In most cases this reduces your diagnostic search process to a single function.

Multiple Queues

By default HoneyBee performs all functions on the global background queue. What if you need to work on the main queu?

HoneyBee.start(on:DispatchQueue.main){rootinroot.setErrorHandler(handleError).chain(func1)// performed on main queue.chain(func2)// same}

Easy right? Need to change queues? What about NSManagedObjectContexts?

HoneyBee.start(on:DispatchQueue.main){rootinroot.setErrorHandler(handleError).chain(func1)// performed on main queue.setBlockPerformer(DispatchQueue.global()).chain(func2)// performed on global background queue .chain(func3)// performed on global background queue .setBlockPerformer(myMOC).chain(func4)// performed on myMOC's internal queue. }

HoneyBee puts you in complete control of what queue will invoke your functions. This remains true even if the functions themselves call back on different queues than they were invoked from.

Wrap Up

So that’s HoneyBee. Expressive, easy, and safe. Concurrency the way it should be.
If you have any questions, contact me.