Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dart await on constructor

Tags:

dart

future

What pattern should I use in this example to load and process some data. As value returns a value, it's not acceptable to have d as a Future. How can I get the constructor to wait until load has completed before continuing?

void main() {
    var data = new Data(); // load data
    print(data.value()); // data.d is still null
}

class Data {
    String d;
    Data() {
        load();
    }

    Future<void> load() async {
        d = await fn(); // some expensive function (e.g. loading a database)
    }

    String value() {
        return d;
    }
}
like image 981
codythecoder Avatar asked Feb 06 '19 08:02

codythecoder


People also ask

Can you await in a constructor?

It's possible to call this in the constructor, but you can't await an expression that referenced it.

What does await do in Dart?

As per this answer and this article, await is supposed to interrupt code execution and actually wait for the future to complete and then continue executing the rest of the code sequentially. It also suggests that this might block the main thread, which is only logical in that case.

Can we use await in constructor Javascript?

You can only use async/await where you can use promises because they are essentially syntax sugar for promises. You can't use promises in a constructor because a constructor must return the object to be constructed, not a promise.

Is Dart synchronous or asynchronous?

Dart Future If any code blocks the thread of execution (for example, by waiting for a time-consuming operation or blocking on I/O), the program effectively freezes. Asynchronous operations let your program run without getting blocked. Dart uses Future objects to represent asynchronous operations.


1 Answers

You cannot make a constructor asynchronous. An asynchronous function needs to return a Future, and a constructor needs to return an instance of the class itself. Unless the class is a future, the constructor cannot be asynchronous (and even then, it's not really the same thing, and you can't use async/await).

So, if your class needs asynchronous set-up, you should provide the user with a static factory method instead of a constructor. I'd usually hide the constructor then.

class Data {
  String _d;
  Data._();
  static Future<Data> create() async {
    var data = Data._();
    await data._load();
    return data;
  }
  Future<void> _load() async {
    _d = await fn(); 
  }
  String get value => _d;
}

As an alternative design, I wouldn't even put the load method on the class, just do the operation in the static factory method:

class Data {
  String _d;
  Data._(this._d);
  static Future<Data> create() async => Data._(await fn());
  String get value => _d;
}

Obviously other constraints might require that load has access to the object.

like image 171
lrn Avatar answered Sep 22 '22 04:09

lrn