Introducing "Await" for Closure Callbacks

In today's Elements build, .2417, we're extending await support to methods with closure callbacks – such as the many Cocoa APIs.

"Async/Await" is a great pattern, pioneered by C# and adopted by many other languages, including Oxygene, JavaScript and others for making asynchonous code easier to write and understand. But thew downside has been that APIs had to be designed especiually for async/await.

Many platforms, including Cocoa and Android, have a rich existing API based around passing callback closures or methods to APIs. The async call will return right away, and call the closure when done. Up until today, these APIs have bene incompatible with the more advanced await pattern. Until today.

Consider a piece of code like this:

method DownloadData;
begin
  Http.ExecuteRequestAsJson(new HttpRequest(URL), (aResponse) -> begin
    if assigned(aResponse.Content) then begin
      dispatch_async(dispatch_get_main_queue(), () -> begin
        fData := aResponse.Content;
        tableView.reloadData;
      end);
    end;
  end);
end;

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 the new await support for closure callbacks, this can be simplified nicely:

method DownloadData;
begin
  var lResponse := await Http.ExecuteRequestAsJson(new HttpRequest(URL));
  if lassigned(aResponse.Content) then begin
    await dispatch_async(dispatch_get_main_queue());
    fData := lResponse.Content;
    tableView.reloadData;
  end;
end;

The same of course works in RemObjects C# (which has the await keyword by standard), and also in our version of Swift, with its __await language extension:

func downloadData() {
    let response = __await Http.ExecuteRequestAsJson(HttpRequest(URL)) {
    if let content = response.Content {
        __await dispatch_async(dispatch_get_main_queue())
        data := response.Content
        tableView.reloadData()
    }
}

Just as with standard async/await, the compiler will do the hard part of taking apart the surrounding code and wrap what looks like linear code flow into multiple helper methods that will be called under the hood as needed. And of course await for Closure Callbacks works for more complex nexted code structures as well, such as making an await call nested within conditional if statements or loops, or even as part of a parameter list:

print(await getServerResponse())

Await for Closure Callbacks is new in Elements .2417, available now. You can read more about the feature on our documentation site, here.