Best way to handle returning ErrorTypes from asynchronous calls?

20 views
Skip to first unread message

Sam Stigler

unread,
Aug 11, 2015, 6:22:47 PM8/11/15
to Swift Language
Hi,

Do you have any thoughts on the best way to handle returning an ErrorType from an asynchronous call? In particular, I'm wondering whether it would be best to follow the traditional route and return the error as an optional in the completion closure, or just throw the error directly.

I would really like to preserve backwards compatibility with Swift 1.2 as much as possible, but am also wondering but the best way is to do this with Swift 2.

Thanks,

Sam Stigler

Fritz Anderson

unread,
Aug 21, 2015, 8:22:04 AM8/21/15
to Swift Language
On Tuesday, August 11, 2015 at 5:22:47 PM UTC-5, Sam Stigler wrote:
Do you have any thoughts on the best way to handle returning an ErrorType from an asynchronous call? In particular, I'm wondering whether it would be best to follow the traditional route and return the error as an optional in the completion closure, or just throw the error directly.

I’m hesitating over the word “returning.” There are a few different things you could mean by it.

By definition, an asynchronous call is expected to return before the desired action is completed. The calling code could be long-gone before an asynchronous error even occurred; a throw from the async task would have nothing to catch it. Errors resulting from the action would be reported to the completion closure, or to a possible error closure, or not at all. Which you design for depends on what you expect will satisfy the needs of the applications that use your API.

An async call might fail immediately, before it returns — you’re trying to write to a closed descriptor, for instance — so the call can return an error value. The options are
  • Traditional: Return a value that signals failure (in Swift, usually a nil) and sets an optional NSErrorPointer to an NSError. Objective-C callers understand this.
  • Enum: Return an enum with an error case and maybe associated values characterizing the error. I like this for Swift 1.x because I hate by-reference return values and I wasn’t interested in offering a bridge to Objective-C.
  • Swift 2+: Throw. The caller gets a clearer flow of control, at the expense of bridges to earlier code.
Choose what you need; there are always tradeoffs.

Whether the asynchronous call also calls a completion/error closure in the event of an immediate error is an independent question. By instinct, I’d do so: The closure would likely include things that have to happen no matter how promptly the task terminated. Or, the calling code might be in a better position to clean up. Either, or both, depending on the needs of the caller. If your async function returns/throws error in-line as well as allowing a completion/failure closure to handle the error, the caller has choices.
Reply all
Reply to author
Forward
0 new messages