如何在Dart中创建空白的Future +如何返回当前正在进行的Future?

Gre*_*man 4 dart dart-async

我正在尝试创建一个服务器端Dart类,该类执行各种与数据相关的任务。所有这些任务都依赖于首先初始化的数据库。问题在于数据库的初始化是异步发生的(返回Future)。我首先尝试将初始化代码放入构造函数中,但是由于似乎不可行,因此放弃了这种方法。

我现在正在尝试找出如何强制进行数据库初始化,这是访问数据的任何方法调用的第一步。因此,换句话说,当在下面调用tryLogin()时,我想首先检查数据库是否已初始化,并在必要时对其进行初始化。

但是,有两个障碍。如果尚未初始化数据库,则代码很简单-初始化db,然后使用返回的future的then()方法完成其余功能。如果数据库尚未初始化,那么将then()方法附加到什么?

第二个相关问题是,当当前正在初始化数据库但此过程尚未完成时会发生什么?我如何才能收回并返回这个“进行中”的未来?

这是我要处理的代码的基本要点:

class DataManager {
  bool DbIsReady = false;
  bool InitializingDb = false;
  Db _db;

  Future InitMongoDB() {
    print("Initializing MongoDB");
    InitializingDb = true;
    _db = new Db("mongodb://127.0.0.1/test");
    return _db.open().then((_) {
      DbIsReady = true;
      InitializingDb = false;
    });
  }  

  Future<List> attemptLogin(String username, String password) {
    Future firstStep;
    if ((!DbIsReady) && (!InitializingDb) {
       Future firstStep = InitMongoDB()
    }
    else if (InitializingDb) {
       // Need to return the InitMongoDB() Future that's currently running, but how?
    }
    else {
       // How do I create a blank firstStep here? 
    }

    return firstStep.then((_) {
      users = _db.collection("users");
      return // ... rest of code cut out for clarity
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

在此先感谢您的帮助,

格雷格

Gün*_*uer 5

刚回来

return new Future<bool>.value(true); 
// or any other value instead of `true` you want to return.
// or none
// return new Future.value();
Run Code Online (Sandbox Code Playgroud)


mez*_*oni 2

可能的解决方案之一:

import "dart:async";

void main() {
  var dm = new DataManager();
  var selectOne = dm.execute("SELECT 1");
  var selectUsers = dm.execute("SELECT * FROM users");
  var users = selectOne.then((result) {
    print(result);
    return selectUsers.then((result) {
      print(result);
    });
  });

  users.then((result) {
    print("Goodbye");
  });
}

class Event {
  List<Function> _actions = new List<Function>();
  bool _raised = false;

  void add(Function action) {
    if (_raised) {
      action();
    } else {
      _actions.add(action);
    }
  }

  void raise() {
    _raised = true;
    _notify();
  }

  void _notify() {
    if (_actions.isEmpty) {
      return;
    }

    var actions = _actions.toList();
    _actions.clear();
    for (var action in actions) {
      action();
    }
  }
}

class DataManager {
  static const int _STATE_NOT_INITIALIZED = 1;
  static const int _STATE_INITIALIZING = 2;
  static const int _STATE_READY = 3;

  Event _initEvent = new Event();
  int _state = _STATE_NOT_INITIALIZED;

  Future _init() {
    if (_state == _STATE_NOT_INITIALIZED) {
      _state = _STATE_INITIALIZING;
      print("Initializing...");
      return new Future(() {
        print("Initialized");
        _state = _STATE_READY;
        _initEvent.raise();
      });
    } else if (_state == _STATE_INITIALIZING) {
      print("Waiting until initialized");
      var completer = new Completer();
      _initEvent.add(() => completer.complete());
      return completer.future;
    }

    return new Future.value();
  }

  Future execute(String query, [Map arguments]) {
    return _init().then((result) {
      return _execute(query, arguments);
    });
  }

  Future _execute(String query, Map arguments) {
    return new Future.value("query: $query");
  }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Initializing...
Waiting until initialized
Initialized
query: SELECT 1
query: SELECT * FROM users
Goodbye
Run Code Online (Sandbox Code Playgroud)

我认为存在更好的解决方案,但这只是尝试回答你的问题(如果我正确理解你的话)。

PS 于 2014 年 7 月 11 日编辑

稍微修改(带有错误处理)的示例。

Initializing...
Waiting until initialized
Initialized
query: SELECT 1
query: SELECT * FROM users
Goodbye
Run Code Online (Sandbox Code Playgroud)