异步/等待/然后在Dart / Flutter中

时间:2019-02-04 11:28:47

标签: asynchronous dart flutter

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

但是,我只是对其进行了一些试验,并在db.query()函数前面添加了“ await”关键字,并且以某种方式使其开始可以正常工作。您能否解释为什么添加await关键字可以解决此问题?我以为在使用.then()函数时,我们不需要使用await关键字。

这是我的代码:

minusMonths

4 个答案:

答案 0 :(得分:4)

简单地说:

await旨在中断流程直到异步方法完成。 then不会中断处理流程(意味着将执行下一条指令),但是使您可以在异步方法完成后运行代码。

在您的示例中,使用then时无法实现所需的功能,因为代码未在“等待”状态,并且return语句已处理并因此返回空列表。

添加await时,您明确地说:“直到我的Future完成(then部分)之后,再说。

您仅可以使用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) { /*...*/ });

答案 1 :(得分:0)

在使类使用async来使用await时,它的简单逻辑是在函数中建立等待状态,直到检索到要显示的数据为止。

示例:1)就像您单击按钮时一样2)数据首先存储在数据库中,然后使用Future函数来检索数据3)将数据移动到变量中,然后在屏幕上显示4)变量显示为增量在您的关注/个人资料中。

then一步一步地使用代码,将数据存储在变量中,然后移至下一个。

示例:如果我单击“跟随”按钮,直到变量中的数据存储,它将连续检索一些数据以存储,并且不允许下一个函数运行,并且如果一项任务完成而不是转移到另一项任务。

与您的问题一样,我也在社交媒体Flutter应用程序中进行实验,这是我的理解。我希望这会有所帮助。

答案 2 :(得分:0)

添加到以上答案中。

Flutter Application被认为是逐步执行代码,但事实并非如此。 在应用程序的生命周期中将触发许多事件,例如Click Event,Timer等。必须在后台线程中运行一些代码。

后台工作的执行方式:

所以有两个Queues

  1. 微任务队列
  2. 事件队列

Microtask Queue运行不应由任何事件(单击,计时器等)运行的代码。它可以同时包含同步和异步工作。

Event Queue在应用程序中发生任何外部Click事件(如Click事件)时运行,然后在事件循环内完成该块执行。

下图将详细说明执行过程。

enter image description here

注意::在应用程序开发的任何给定点,微任务队列都会运行,然后只有事件队列才能运行。

答案 3 :(得分:0)

使用期货:异步,等待,然后和期货

asyncawait关键字提供了一种声明性的方式来定义异步函数并使用它们的结果。使用asyncawait时,请记住以下两个基本准则:

  • 要定义异步函数,请在函数正文之前添加async
  • await关键字仅在async函数中起作用。

下面是将main()从同步功能转换为异步功能的示例。

首先,在函数正文之前添加async关键字:

void main() async { ··· }

如果函数具有声明的返回类型,则将类型更新为Future<T>,其中T是函数返回的值的类型。如果该函数未明确返回值,则返回类型为Future<void>

Future<void> main() async { ··· }

现在您有了async函数,可以使用await关键字等待将来完成:

print(await createOrderMessage());

.Then((value){…})future成功完成(带有值)时调用的回调。

await createOrderMessage().then((value) {...});

异步,等待,然后和未来的完整示例

Future<String> createOrderMessage() async {
  var order = await fetchUserOrder();
  return 'Your order is: $order';
}

Future<String> fetchUserOrder() =>
    // Imagine that this function is
// more complex and slow.
Future.delayed(
  Duration(seconds: 2),
      () => 'Large Latte',
);

Future<void> main() async {
  print('Fetching user order...');
  print(await createOrderMessage().then((value) {
    print(value);
    return value;
  }));
}