从Dart中的组件构造函数调用异步方法

typ*_*def 18 constructor asynchronous dart

我们假设在Dart中初始化MyComponent需要向服务器发送HttpRequest.是否有可能同步构造一个对象并推迟"实际"初始化直到响应回来?

在下面的示例中,在打印"完成"之前不会调用_init()函数.有可能解决这个问题吗?

import 'dart:async';
import 'dart:io';

class MyComponent{
  MyComponent() {
    _init();
  }

  Future _init() async {
    print("init");
  }
}

void main() {
  var c = new MyComponent();
  sleep(const Duration(seconds: 1));
  print("done");
}
Run Code Online (Sandbox Code Playgroud)

输出:

done
init
Run Code Online (Sandbox Code Playgroud)

Kan*_*sto 73

处理这个问题的最好方法可能是使用工厂函数,它调用私有构造函数。

在 Dart 中,私有方法以下划线开头,“额外的”构造函数需要一个形式为 的名称ClassName.constructorName,因为 Dart 不支持函数重载。这意味着私有构造函数需要一个以下划线开头的名称(MyComponent._create在下面的示例中)。

import 'dart:async';
import 'dart:io';

class MyComponent{
  /// Private constructor
  MyComponent._create() {
    print("_create() (private constructor)");

    // Do most of your initialization here, that's what a constructor is for
    //...
  }

  /// Public factory
  static Future<MyComponent> create() async {
    print("create() (public factory)");

    // Call the private constructor
    var component = MyComponent._create();

    // Do initialization that requires async
    //await component._complexAsyncInit();

    // Return the fully initialized object
    return component;
  }
}

void main() async {
  var c = await MyComponent.create();

  print("done");
}
Run Code Online (Sandbox Code Playgroud)

这样,就不可能意外地从类中创建一个不正确初始化的对象。唯一可用的构造函数是私有的,因此创建对象的唯一方法是使用工厂,它执行正确的初始化。

  • 这也向发送者隐藏了对象创建的详细信息 (2认同)
  • 您可以在属性中使用“late”关键字@Marco (2认同)

Gün*_*uer 20

构造函数只能返回它是(MyComponent)的构造函数的类的实例.您的要求需要返回Future<MyComponent>不受支持的构造函数.

您需要创建一个需要由类的用户调用的显式初始化方法,如:

class MyComponent{
  MyComponent();

  Future init() async {
    print("init");
  }
}

void main() async {
  var c = new MyComponent();
  await c.init();
  print("done");
}
Run Code Online (Sandbox Code Playgroud)

或者您在consturctor中开始初始化并允许组件的用户等待初始化完成.

class MyComponent{
  Future _doneFuture;

  MyComponent() {
    _doneFuture = _init();
  }

  Future _init() async {
    print("init");
  }

  Future get initializationDone => _doneFuture
}

void main() async {
  var c = new MyComponent();
  await c.initializationDone;
  print("done");
}
Run Code Online (Sandbox Code Playgroud)

什么_doneFuture时候已经完成await c.initializationDone立即返回,否则它等待未来先完成.