Await Expressions
An await
expression can be used to write asynchronous code in a linear fashion. It can be applied to methods that return a Task
, as well as to methods that expect a callback closure as final parameter.
Code can be written as if the methods in question return a value right away, and the compiler will handle the task of unwrapping the provided code and handle the callbacks properly. Under the hood, __await
will break the method into different parts, scheduling them to be executed asynchronously once the awaited actions have been completed.
Await with Tasks
Await with Tasks works similar to the "async/await" pattern in other languages, such as C#, Oxygene or even modern JavaScript. A method is declared as returning a special Task
type either explicitly, or using language sugar such as the C# async
keyword. The returned Task
instance can be used to keep track of the status, and be notified when the result is available – which the __await
keyword abstracts:
func test() -> Task<String> {
let task = Task<String>() {
Thread.Sleep(10000)
return "Result!"
}
task.Start()
return task
}
...
func OtherMethod() {
let message = __await test();
print(message)
}
At the point of the __await
in OtherMethod, the actual method containing the await call will finish. All subsequent code (such as the call to print
in the example above) will be wrapped in a helper type, and execute once the task as completed.
Await with Closures
Await can also be used with methods that take a "callback" closure as last parameter. The parameters of the closure will turn into return values of the call. For example, consider the following call using Elements RTL's Http
class:
func downloadData() {
Http.ExecuteRequestAsJson(HttpRequest(URL)) { response in
if let content = response.Content {
dispatch_async(dispatch_get_main_queue()) {
data = content
tableView.reloadData()
}
}
}
}
This code uses two nested closures, first to wait for the response of the network request, and then to process its results on the main UI thread. With await
this can be unwrapped nicely:
func downloadData() {
let response = __await Http.ExecuteRequestAsJson(HttpRequest(URL)) {
if let content = response.Content {
__await dispatch_async(dispatch_get_main_queue())
data := content
tableView.reloadData()
}
}
Note how the parameter of the first closure, response
becomes a local variable, and how __await
is used without return value on the dispatch_async
call.
For callbacks that return more than one parameter, __await
will return a tuple, e.g.:
let (aValue, aError) = __await tryToGetValueOrReturnError()
...