Dart Flutter,帮我理解期货

Dart Flutter, help me understand futures

查看此代码:

class SomeClass{
  String someVariable;
  SomeClass();
  
  Future<String> getData ()  async {
    Response response = await get('http://somewebsite.com/api/content');
    
    Map map = jsonDecode(response.body); // do not worry about statuscode, trying to keep it minimal
    someVariable = map['firstName'];
    return 'This is the first name : $someVariable';
  }
}

现在看主要内容:

void main(){
  String someFunction() async {
    SomeClass instance = SomeClass(); // creating object
    String firstNameDeclaration = await instance.getData().then((value) => value); 
    return firstNameDeclaration;
  }
}

使用 Future 时,就像 firstNameDeclaration 的情况一样,为什么我必须使用 .then() 方法来访问字符串对象,因为我正在等待函数完成? 在网上搜索时,有些人使用 .then() 其他人不使用,我很困惑。

请帮助我更清楚地了解 Futures 和异步函数的整体工作原理。

基本上,您应该使用 awaitthen()。但是,Dart guidelines 提倡您应该更喜欢使用 await 而不是 then() :

此代码:

Future<int> countActivePlayers(String teamName) {
  return downloadTeam(teamName).then((team) {
    if (team == null) return Future.value(0);

    return team.roster.then((players) {
      return players.where((player) => player.isActive).length;
    });
  }).catchError((e) {
    log.error(e);
    return 0;
  });
}

应替换为:

Future<int> countActivePlayers(String teamName) async {
  try {
    var team = await downloadTeam(teamName);
    if (team == null) return 0;

    var players = await team.roster;
    return players.where((player) => player.isActive).length;
  } catch (e) {
    log.error(e);
    return 0;
  }
}

在你的情况下,你应该写:

void main(){
  Future<String> someFunction() async {
    SomeClass instance = SomeClass(); // creating object
    String firstNameDeclaration = await instance.getData();
    return firstNameDeclaration;
    // Or directly : return await instance.getData();
    // Or : return instance.getData();
  }
}

背景

异步操作让您的程序在等待另一个操作完成时完成工作。下面是一些常见的异步操作:

  • 正在通过网络获取数据。
  • 正在写入数据库。
  • 正在从文件中读取数据。

要在 Dart 中执行异步操作,可以使用 Future class 和 async等待个关键字。

当异步函数调用“await”时,它被转换为一个Future,并被放入执行队列。当等待的未来完成时,调用函数被标记为准备执行,并将在稍后的某个时间点恢复。重要的区别是在此模型中不需要暂停任何线程。

期货与异步等待

当一个async函数调用“await”时,它被转换成一个Future , 并放入执行队列。当等待的未来完成时,调用函数被标记为准备执行,并将在稍后的某个时间点恢复。重要的区别是在此模型中不需要暂停任何线程。

async-await 只是一种定义异步函数并将其结果用于 Future 的声明方式,它提供了语法糖来帮助您编写涉及 Futures 的干净代码。

考虑这个涉及 Futures 的 dart 代码 -

Future<String> getData(int number) {
  return Future.delayed(Duration(seconds: 1), () {
    return 'this is a future string $number.';
  });
}

main(){
  getData(10).then((data) => {
    print(data)
  });
}

正如您在使用 Futures 时看到的那样,当函数 return 一个未来值时,您可以使用 then 回调。如果只有一个“then”回调,这很容易管理,但是一旦有许多嵌套的“then”回调,情况就会迅速升级 -

Future<String> getProductCostForUser() {
  return getUser().then((user) => {
    var uid = user.id;
    return getOrder(uid).then((order) => {
      var pid = order.productId;
      return getProduct(pid).then((product) => {
        return product.totalCost;
      });
    });
  });
}

main(){
  getProductCostForUser().then((cost) => {
    print(cost);
  });
}

当有多个链接的“then”回调时,代码会变得非常难以阅读和管理。 "async-await" 解决了这个问题。上面链接的“then”回调可以通过使用 "async-await" 来简化,就像这样 -

Future<String> getProductCostForUser() async {
  var user = await getUser();
  var order = await getOrder(user.uid);
  var product = await getProduct(order.productId);
  return product.totalCost;
}

main() async {
  var cost = await getProductCostForUser();
  print(cost);
}

如您所见,当存在链式“then”回调时,上面的代码更具可读性和易于理解。

我希望这能解释一些关于“async-await”和 Futures 的基本概念和理解。

您可以进一步阅读主题和示例here