首页 > 解决方案 > 异步/等待/然后在 Dart/Flutter 中

问题描述

我有一个颤振应用程序,我在其中使用 SQFLITE 插件从 SQLite DB 获取数据。在这里,我面临一个奇怪的问题。据我了解,我们使用 async/await 或 then() 函数进行异步编程。这里我有一个 db.query() 方法,它执行一些 SQL 查询以从数据库中获取数据。在这个函数获取数据之后,我们在 .then() 函数中做一些进一步的处理。但是,在这种方法中,我遇到了一些问题。从我调用这个 getExpensesByFundId(int fundId) 函数的地方,它似乎无法正确获取数据。它应该返回 Future> 对象,然后在数据可用时将其转换为 List 。但是当我打电话时它不起作用。

但是,我只是对它进行了一些实验,并在 db.query() 函数前面添加了“await”关键字,不知何故它刚刚开始正常工作。你能解释一下为什么添加 await 关键字可以解决这个问题吗?我想在使用 .then() 函数时,我们不需要使用 await 关键字。

这是我的代码:

Future<List<Expense>> getExpensesByFundId(int fundId) async {
    Database db = await database;

    List<Expense> expenseList = List();

   // The await in the below line is what I'm talking about

    await db.query(expTable,where: '$expTable.$expFundId = $fundId')
        .then((List<Map<String,dynamic>> expList){
      expList.forEach((Map<String, dynamic> expMap){
        expenseList.add(Expense.fromMap(expMap));
      });
    });
    return expenseList;
  }

标签: flutterdartasynchronousasync-await

解决方案


简单来说:

await是为了中断过程流程,直到async方法完成。 then但是不会中断流程(意味着将执行下一条指令),而是使您能够在async方法完成时运行代码。

在您的示例中,您无法在使用时实现您想要then的,因为代码不是“等待”并且return语句已被处理,因此返回一个空列表。

当你添加 时,你明确地说:'在我的方法完成(即部分)await之前不要走得更远。Futurethen

您可以按如下方式编写代码以仅使用以下方式获得相同的结果await

Future<List<Expense>> getExpensesByFundId(int fundId) async {
    Database db = await database;

    List<Expense> expenseList = List();

    List<Map<String,dynamic>> expList = await db.query(expTable,where: '$expTable.$expFundId = $fundId');
    expList.forEach((Map<String, dynamic> expMap) {
        expenseList.add(Expense.fromMap(expMap));
    });

    return expenseList;
}

您也可以选择仅使用该then部分,但您需要确保getExpensesByFundId之后正确调用:

Future<List<Expense>> getExpensesByFundId(int fundId) async {
    Database db = await database;

    List<Expense> expenseList = List();
    
    return db.query(expTable,where: '$expTable.$expFundId = $fundId')
        .then((List<Map<String,dynamic>> expList){
      expList.forEach((Map<String, dynamic> expMap){
        expenseList.add(Expense.fromMap(expMap));
      });
    });
}

// call either with an await
List<Expense> list = await getExpensesByFundId(1);
// or with a then (knowing that this will not interrupt the process flow and process the next instruction
getExpensesByFundId(1).then((List<Expense> l) { /*...*/ });

推荐阅读