如何在Dart中创建一个空白的Future?如何返回当前正在进行的未来? [英] How do I create a blank Future in Dart + how do I return a future currently in progress?

查看:1091
本文介绍了如何在Dart中创建一个空白的Future?如何返回当前正在进行的未来?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我现在试图找出如何强制数据库初始化作为访问数据的任何方法调用的第一步。换句话说,当下面调用attemptLogin()时,我想首先检查数据库是否已经初始化并在必要时初始化它。



但是,有两个障碍。如果数据库尚未初始化,代码很简单 - 初始化db,然后使用返回的future的then()方法来执行其余的函数。如果数据库还没有初始化,我该如何附加我的then()方法?



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



这是我试图转义的代码的基本要点:

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

未来InitMongoDB(){
print(初始化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){
//需要返回InitMongoDB()当前正在运行的Future,但是如何?
}
else {
//如何在这里创建一个空白的firstStep?
}

return firstStep.then((_){
users = _db.collection(users);
return // ...其余的代码为了清晰起见
} );
}
}

感谢您的帮助, p>

Greg

解决方案

其中一个可能的解决方案:

  importdart: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;

事件_initEvent =新事件();
int _state = _STATE_NOT_INITIALIZED;

未来_init(){
if(_state == _STATE_NOT_INITIALIZED){
_state = _STATE_INITIALIZING;
print(正在初始化...);
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();
}

未来的执行(String query,[Map arguments]){
return _init()。then((result){
return _execute );
});
}

未来_execute(String查询,Map参数){
return new Future.value(query:$ query);
}
}

输出:


b $ b

 初始化... 
等待直到初始化
初始化
查询:SELECT 1
查询:SELECT * FROM users
再见

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



PS于2014年7月11日修订



稍微修改(含错误处理)示例。

 
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 DataManager {
static const int _STATE_NOT_INITIALIZED = 1;
static const int _STATE_INITIALIZING = 2;
static const int _STATE_READY = 3;
static const int _STATE_FAILURE = 4;

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

未来_ensureInitialized(){
switch(_state){
case _STATE_NOT_INITIALIZED:
_state = _STATE_INITIALIZING;
print(正在初始化...);
new Future((){
print(Initialized);
_state = _STATE_READY;
// throw null;
_initEvent.complete $ b})。catchError((e,s){
print(Failure);
_initEvent.completeError(e,s);
}

break;
case _STATE_INITIALIZING:
print(Waiting until initialized);
break;
case _STATE_FAILURE:
print(Failure detected);
break;
默认值:
print(Aleady intialized);
break;
}

return _initEvent.future;
}

未来的执行(String query,[Map arguments]){
return _ensureInitialized()。then((result){
return _execute );
});
}

未来_execute(String查询,Map参数){
return new Future.value(query:$ query);
}
}


I'm trying to create a server-side Dart class that performs various data-related tasks. All of these tasks rely on the database having been first initialized. The problem is that the init of the database happens asynchronously (returns a Future). I first tried to put the init code into the constructor, but have given up on this approach as it seems to not be viable.

I am now attempting to figure out how to force the DB initialization as a first step in any method call that accesses data. So in other words, when attemptLogin() is called below, I'd like to first check if the DB has been initialized and initialize it if necessary.

However, there are two obstacles. If the database hasn't been initialized, the code is straightforward - initialize the db, then use the then() method of the returned future to do the rest of the function. If the db is not yet initialized, what do I attach my then() method to?

Second related question is what happens when a database is currently being initialized but this process is not yet complete? How can I pull in and return this "in-progress" Future?

This is the basic gist of the code I'm trying to wrangle:

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
    });
  }
}

Thanks in advance for your help,

Greg

解决方案

One of the possible solutions:

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");
  }
}

Output:

Initializing...
Waiting until initialized
Initialized
query: SELECT 1
query: SELECT * FROM users
Goodbye

I think that exist better solution but this just an attempt to answer on your question (if I correctly understand you).

P.S. EDITED at 11 July 2014

Slightly modified (with error handling) example.

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 DataManager {
  static const int _STATE_NOT_INITIALIZED = 1;
  static const int _STATE_INITIALIZING = 2;
  static const int _STATE_READY = 3;
  static const int _STATE_FAILURE = 4;

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

  Future _ensureInitialized() {
    switch (_state) {
      case _STATE_NOT_INITIALIZED:
        _state = _STATE_INITIALIZING;
        print("Initializing...");
        new Future(() {
          print("Initialized");
          _state = _STATE_READY;
          // throw null;
          _initEvent.complete();
        }).catchError((e, s) {
          print("Failure");
          _initEvent.completeError(e, s);
        });

        break;    
      case _STATE_INITIALIZING:
        print("Waiting until initialized");
        break;
      case _STATE_FAILURE:
        print("Failure detected");
        break;
      default:
        print("Aleady intialized");
        break;
    }

    return _initEvent.future;
  }

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

  Future _execute(String query, Map arguments) {
    return new Future.value("query: $query");
  }
}

这篇关于如何在Dart中创建一个空白的Future?如何返回当前正在进行的未来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆