Dart 关于使用期货和完成人的问题

Dart 关于使用期货和完成人的问题,dart,dart-async,Dart,Dart Async,嘿,我已经阅读了所有我能找到的关于期货的资料,但我想了解更多关于正确使用的建议 我正在编写一个API库,它弥合了HTTP请求和应用程序之间的鸿沟。因此,在大多数情况下,我使用HTTP返回的future,但是有时数据已经被检索到了。这是使用补全符的合适时间吗 前 String_someData=”“; 未来的getSomeData(){ 如果(_someData==“”){ 返回Api.getSomeData().then((字符串someData){ _someData=someData; 返回

嘿,我已经阅读了所有我能找到的关于期货的资料,但我想了解更多关于正确使用的建议

我正在编写一个API库,它弥合了HTTP请求和应用程序之间的鸿沟。因此,在大多数情况下,我使用HTTP返回的future,但是有时数据已经被检索到了。这是使用补全符的合适时间吗

String_someData=”“;
未来的getSomeData(){
如果(_someData==“”){
返回Api.getSomeData().then((字符串someData){
_someData=someData;
返回一些数据;
});
}否则{
var completer=new completer();
完成者。完成(_someData);
返回completer.future;
}
}
-编辑-如果我创建了一个完成符,但最终没有使用它的未来或调用complete。这会导致内存泄漏吗?我应该调用它的完整方法还是以某种方式处理它


谢谢:)

请改用
async
函数

import "dart:async";

String _someData = "";

Future<String> getSomeData() async {
  if (_someData == "") {
    _someData = await Api.getSomeData();
  }

  return _someData;
}
导入“dart:async”;
字符串_someData=“”;
Future getSomeData()异步{
如果(_someData==“”){
_someData=await Api.getSomeData();
}
返回一些数据;
}
编译器大约生成以下代码:

import "dart:async";

String _someData = "";

Future<String> getSomeData() {
  var $_awaiter = new Completer<String>();
  try {
    if (_someData == "") {
      Api.getSomeData().then(($) {
        $_awaiter.complete($);
      }).catchError((e, s) {
        $_awaiter.completeError(e, s);
      });

      return $_awaiter.future;
    } else {
      $_awaiter.complete(_someData);
      return $_awaiter.future;
    }
  } catch (e, s) {
    $_awaiter.completeError(e, s);
    return $_awaiter.future;
  }
}
导入“dart:async”;
字符串_someData=“”;
未来的getSomeData(){
var$_waiter=new Completer();
试一试{
如果(_someData==“”){
Api.getSomeData()。然后($){
$\等待者。完成($);
}).catchError((e,s){
$\等待者。完成错误(e,s);
});
返回$u waiter.future;
}否则{
$\u waiter.complete(\u someData);
返回$u waiter.future;
}
}渔获物(东、南){
$\等待者。完成错误(e,s);
返回$u waiter.future;
}
}

如果可以立即访问该值,则可以使用命名构造函数
Future.value
。您不需要一个
完成符

String _someData = "";

Future<String> getSomeData(){
  if (_someData == ""){
    return Api.getSomeData().then((String someData){
      _someData = someData;
      return _someData;
    });
  } else {
    return new Future.value(_someData);
  }
}
String_someData=”“;
未来的getSomeData(){
如果(_someData==“”){
返回Api.getSomeData().then((字符串someData){
_someData=someData;
返回一些数据;
});
}否则{
返回新的Future.value(_someData);
}
}

对于你的第二个问题,如果你创建了一个
完成器
,而不使用它,我想垃圾收集器会在你的代码中不再有对它的引用时释放它的内存。

这难道不会为将来设置一些数据吗?在Api.getSomeData()返回其未来之前,该块不会被阻塞吗?@Krtko Operator
wait
always
unwrap
future。因此,在本例中,您将得到一个
Future.result
。而且它不会阻止调用
Api.getSomeData()
,它将以与使用
未来相同的方式链接计算。然后()
,@Krtko它不会阻止。操作员
await
总是为您生成一个
完成符。当
Completer
初始化后,则
Completer.future
将立即返回而不阻塞。当
Api.getSomeData()
将完成时,它将完成
Completer
。下一步是调用
Completer.future.whenComplete()
。所以没有任何阻塞操作,因为所有这些操作显然都没有被阻塞,而是由内部实现通过微任务或计时器进行调度。这种方式的缺点是,如果您将
\u somedata
从字段更改为
getter
,并且如果此
getter
将引发异常,则您的函数
getSomeData
不会返回结果(
Future
,在本例中),但会引发异常。这意味着它是一个不安全的(半异步)实现,需要在使用它的其他代码中采取特殊的预防措施,因为它不能确保它返回一个
未来的
String _someData = "";

Future<String> getSomeData(){
  if (_someData == ""){
    return Api.getSomeData().then((String someData){
      _someData = someData;
      return _someData;
    });
  } else {
    return new Future.value(_someData);
  }
}