Oleg Sklyar
Oleg Sklyar

Reputation: 10082

Why 'await' cannot be used in ordinary functions?

Correction: as follows from two answers, the problem looks to be specific to dart as C# implements Task.Wait allowing to achieve the desired effect. I would be grateful for any further information on the reasons why this is not possible in dart or how to achieve it there. I would be happy to close the question in its current form.


There are situations where it could make sense to have synchronous functions use asynchronous calls internally waiting for their completion before delivering the result. This is explicitly not allowed in both C# and Dart: anything that uses await must be marked as async (thus returning a future).

A simple example in Dart, but the same is valid for C#:

Disclaimer: this is not how I would do things, so do not suggest a "correct" solution of converting all methods to async; the code here is just to illustrate the question.

I have a fully asynchronous implementation of a generic wrapper for HTTP requests to some particular REST API. It does some login, authentication etc.:

class RequestProcessor {
     Future post(String path, [payload]) async {
          return request("POST", path, payload);
     }
}

I would like to implement a high-level user-facing API translating to requests to the REST-API. Some of those methods I'd like to have synchronous. This is what I would like and am not allowed to have:

class API {
    final RequestProcessor processor;

    API(this.processor);

    // this takes long and should be asynchronous, happy with a future (OK)
    Future getQueryResults(query) async {
        return await processor.post("/query", query);
    }

    // here I would prefer to have it synchronous (COMPILE ERROR)
    String getVersion() {
        return await processor.post("/version");
    }
}

Question: Why is this not allowed?

Upvotes: 1

Views: 480

Answers (4)

lrn
lrn

Reputation: 71663

It's a design choice. Dart is single-threaded - each synchronous function call will run to completion before allowing any other code to run. If you allow a synchronous function to block until a future is complete, then no other code will run and the future will never complete (because the code that would complete it can't run).

It is possible to have a system that allows other code to run while one synchronous function is blocked. That requires either having more than one active stack (parallel or not), or implicitly transforming the entire program to be async. Neither choice is great when you compile to JavaScript, so Dart did not try to do that.

Upvotes: 4

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657348

In Dart marking a function/method async tells the VM that it needs to rewrite the code before executing it. await doesn't change an async function to a sync one, the function is still async, it just allows nicer syntax than then(() { return ...then(() { return...})}) chains.

If you make an async call everything following is async, there is nothing you can do about it.

Upvotes: 0

NeddySpaghetti
NeddySpaghetti

Reputation: 13495

The await is an asynchronous wait so it does not make sense to have it in a synchronous function. To be asynchronous the method needs to return when the awaited operation is initiated, whereas the synchronous method needs to run to completion.

You can use a synchronous wait instead, in which case your method does not need to be async. In C# you can do this by calling the Wait() method on the returned task.

Upvotes: 3

Nir
Nir

Reputation: 29594

Because waiting and returning a future is fundamentally different.

Returning a future frees the current thread and optionally schedules a continuation for later, waiting blocks the current thread.

For example, in a UI thread, returning a future is fine but waiting will cause the UI to hang, in a web server thread waiting will block the thread and prevent the web server from handling more request, etc.

It's even possible waiting for what should be an async operation will cause a deadlock.

.net provide Task.Wait for when you know waiting is fine, I don't know about dart - but this is not automatic (except for await inside catch clauses in async methods in C#)

Upvotes: 2

Related Questions