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()
...

See Also

  • await Expressions in Oxygene
  • await keyword in C#