Can Constructors Be Async

Can constructors be async?

Constructor acts very similarly to a method returning the constructed type. And async method can't return just any type, it has to be either “fire and forget” void, or Task.

If the constructor of type T actually returned Task<T>, that would be very confusing, I think.

If the async constructor behaved the same way as an async void method, that kind of breaks what constructor is meant to be. After constructor returns, you should get a fully initialized object. Not an object that will be actually properly initialized at some undefined point in the future. That is, if you're lucky and the async initialization doesn't fail.

All this is just a guess. But it seems to me that having the possibility of an async constructor brings more trouble than it's worth.

If you actually want the “fire and forget” semantics of async void methods (which should be avoided, if possible), you can easily encapsulate all the code in an async void method and call that from your constructor, as you mentioned in the question.

Async/Await Class Constructor

This can never work.

The async keyword allows await to be used in a function marked as async but it also converts that function into a promise generator. So a function marked with async will return a promise. A constructor on the other hand returns the object it is constructing. Thus we have a situation where you want to both return an object and a promise: an impossible situation.

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.

There are two design patterns to overcome this, both invented before promises were around.

  1. Use of an init() function. This works a bit like jQuery's .ready(). The object you create can only be used inside it's own init or ready function:

    Usage:

    var myObj = new myClass();
    myObj.init(function() {
    // inside here you can use myObj
    });

    Implementation:

    class myClass {
    constructor () {

    }

    init (callback) {
    // do something async and call the callback:
    callback.bind(this)();
    }
    }
  2. Use a builder. I've not seen this used much in javascript but this is one of the more common work-arounds in Java when an object needs to be constructed asynchronously. Of course, the builder pattern is used when constructing an object that requires a lot of complicated parameters. Which is exactly the use-case for asynchronous builders. The difference is that an async builder does not return an object but a promise of that object:

    Usage:

    myClass.build().then(function(myObj) {
    // myObj is returned by the promise,
    // not by the constructor
    // or builder
    });

    // with async/await:

    async function foo () {
    var myObj = await myClass.build();
    }

    Implementation:

    class myClass {
    constructor (async_param) {
    if (typeof async_param === 'undefined') {
    throw new Error('Cannot be called directly');
    }
    }

    static build () {
    return doSomeAsyncStuff()
    .then(function(async_result){
    return new myClass(async_result);
    });
    }
    }

    Implementation with async/await:

    class myClass {
    constructor (async_param) {
    if (typeof async_param === 'undefined') {
    throw new Error('Cannot be called directly');
    }
    }

    static async build () {
    var async_result = await doSomeAsyncStuff();
    return new myClass(async_result);
    }
    }

Note: although in the examples above we use promises for the async builder they are not strictly speaking necessary. You can just as easily write a builder that accept a callback.


Note on calling functions inside static functions.

This has nothing whatsoever to do with async constructors but with what the keyword this actually mean (which may be a bit surprising to people coming from languages that do auto-resolution of method names, that is, languages that don't need the this keyword).

The this keyword refers to the instantiated object. Not the class. Therefore you cannot normally use this inside static functions since the static function is not bound to any object but is bound directly to the class.

That is to say, in the following code:

class A {
static foo () {}
}

You cannot do:

var a = new A();
a.foo() // NOPE!!

instead you need to call it as:

A.foo();

Therefore, the following code would result in an error:

class A {
static foo () {
this.bar(); // you are calling this as static
// so bar is undefinned
}
bar () {}
}

To fix it you can make bar either a regular function or a static method:

function bar1 () {}

class A {
static foo () {
bar1(); // this is OK
A.bar2(); // this is OK
}

static bar2 () {}
}

Can we call an async method from a constructor?

You cannot have async constructors.

One alternative is to have async factory methods:

public class MyModel
{
public SFOpportunity Opportunity { get; set; }
private MyModel() { }

public static async Task<MyModel> CreateAsync(string id)
{
var result = new MyModel();
await result.setOpportunityAsync(id);
return result;
}

private async Task setOpportunityAsync(string id)
{
...
}
}

Call asynchronous method in constructor?

The best solution is to acknowledge the asynchronous nature of the download and design for it.

In other words, decide what your application should look like while the data is downloading. Have the page constructor set up that view, and start the download. When the download completes update the page to display the data.

I have a blog post on asynchronous constructors that you may find useful. Also, some MSDN articles; one on asynchronous data-binding (if you're using MVVM) and another on asynchronous best practices (i.e., you should avoid async void).

How can I use async in a named constructor?

Constructors can't be asynchronous. If you find yourself wanting an asynchronous constructor, you instead could make a static asynchronous method that acts like an asynchronous factory. From the perspective of the caller, there isn't much difference (and what differences there are mostly favor having a static method). You additionally could make all other constructors (including the default constructor) private to force callers to use the static method to get an instance of your class.

That said, in your case, you might not even need a class at all. Do you intend to have other methods on an HttpService? Is your HttpService maintaining any internal state? If not, then you would be better off with a freestanding function.

c# calling async function from constructor gives green underline in VS

Indeed, C# / .NET does not currently support async constructors, so you'd have to use either an async static factory method, or an async initialize method after the constructor has finished; however - this line is not true:

that is just a workaround to get rid of the green underline.

This is not just a workaround; if you haven't awaited an async method, then you don't know when it has finished, so you can't rely on the state that it is meant to initialize - and you have have inadvertent thread-safety issues (as you now effectively have two active executions, which is comparable to two active threads). As such, refactoring (in one of the ways cited above) is necessary for correctness.

Can async/await be used in constructors?

Without trying to fortune-tell about future decisions, let's concentrate on practicality and what is already known.

ES7, like ES6 before it will try to be a backwards compatible expansion to the language. With that in mind, a backwards compatible constructor function is essentially a regular function (with some runtime restrictions) that's meant to be invoked with the new keyword. When that happens, the function's return value gets special treatment, specifically, non-object return values are ignored and the newly allocated object is returned while object return values are returned as is (and the newly allocated object is thrown away). With that, your code would result in a promise being returned and no "object construction" would take place. I don't see the practicality of this and I suppose if anybody takes the time to find what to do with such code it will be rejected.

async constructor functions in TypeScript?

A constructor must return an instance of the class it 'constructs'. Therefore, it's not possible to return Promise<...> and await for it.

You can:

  1. Make your public setup async.

  2. Do not call it from the constructor.

  3. Call it whenever you want to 'finalize' object construction.

    async function run() 
    {
    let topic;
    debug("new TopicsModel");
    try
    {
    topic = new TopicsModel();
    await topic.setup();
    }
    catch (err)
    {
    debug("err", err);
    }
    }

dart await on constructor

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.



Related Topics



Leave a reply



Submit