【问题标题】:Async function returns two different results after another异步函数一个接一个地返回两个不同的结果
【发布时间】:2021-05-20 02:18:13
【问题描述】:

我编写了一个异步 Flutter/Dart 函数,在我看来它的行为出乎意料。以下代码结构:

static Future<bool> verifySometing() async {
   try {
      await getCloudData().then((snapshot) {
         if (snapshot.exists && snapshot.hasData) {
            bool dataValid = await validateData(snapshot.data);
            if (dataValid) {
               print('Data is correct');
               return true;
            }
         }
      });
   } catch (e) {
      print('Error $e');
      return false;
   }
   print('Something went wrong');
   return false;
}

预期结果是该函数等待云数据,然后等待验证,如果数据有效则返回 true。在这种情况下,控制台将显示以下内容并且函数将返回 true:

Data is correct

实际情况是控制台显示如下输出,函数先返回真,后返回假:

Data is correct
Something went wrong

这与我想知道的关于 Dart 中的函数的任何事情都背道而驰,因为我一直认为一旦触发 return,函数就完成了。任何想法这是如何发生的?

【问题讨论】:

  • 请记住,当您使用await 时,您不需要使用then,反之亦然。加上await 停止代码的执行,同时释放线程以进行其他工作,并且仅在等待的工作完成时继续。与then不同,它不会停止执行下面的代码。

标签: function flutter dart asynchronous async-await


【解决方案1】:

问题在于这一行。

await getCloudData().then((snapshot) {

在这里,您不仅附加了awaiting,还附加了then 回调。所以实际上,无论您返回什么都是callback 函数的返回值,即(snapshot) {}

您需要传递给then 的回调函数将return true 作为await 的结果提供给我们。

所以,如果你会放类似的东西

var bool = await getCloudData().then((snapshot) { ..... });

那么这个bool 就等于true。而已。您的 main 函数没有返回。

改成这个,

var snapshot = await getCloudData();
if (snapshot.exists && snapshot.hasData) {
  bool dataValid = await validateData(snapshot.data);
  if (dataValid) {
    print('Data is correct');
    return true;
  }
}

希望我能解释清楚。

【讨论】:

    【解决方案2】:

    你的假设有一些错误。

    首先,您已将then 附加到getCloudData() 返回的未来。这意味着您不是在等待getCloudData(),而是在等待getCloudData().then(...) 返回的additional 未来,并且该未来将在传递给它的回调函数完成时返回。 (除非第一个 future 抛出错误,否则回调 被调用。)

    其次,回调函数在自己的范围内运行。所以这段代码没有做你认为它在做的事情:

    bool dataValid = await validateData(snapshot.data);
    if (dataValid) {
      print('Data is correct');
      return true;
    }
    

    此返回将影响 回调 函数,而不是 verifySomething 函数。

    鉴于这些,操作顺序如下:

    1. validateSomething 函数 awaits getCloudData().then(...)
    2. getCloudData() 被调用。
    3. getCloudData() 返回,传递给then 的回调被调用。
    4. (假设快照有数据)validateData 被调用。
    5. (假设数据验证成功)打印“数据正确”,回调函数返回true
    6. validateSomething 被通知等待的未来已经完成,因此继续执行。
    7. “出了点问题”被打印出来,validateSomething 函数返回 false

    一般来说,混合async/awaitthen 模式时,这类错误很常见。除非您知道自己在做什么,否则请坚持使用其中一种,最好是async/await 模式。例如,重构代码以消除对then 的调用如下:

    static Future<bool> verifySometing() async {
       try {
          final snapshot = await getCloudData();
          if (snapshot.exists && snapshot.hasData) {
            bool dataValid = await validateData(snapshot.data);
            if (dataValid) {
              print('Data is correct');
              return true;
            }
          }
       } catch (e) {
          print('Error $e');
          return false;
       }
       print('Something went wrong');
       return false;
    }
    

    现在无需处理讨厌的闭包,return 将按预期从validateSomething 返回,您无需处理回调和范围等问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-15
      • 2022-11-22
      • 2019-05-22
      • 2020-09-17
      • 2019-11-17
      • 2016-02-22
      • 1970-01-01
      • 2022-08-13
      相关资源
      最近更新 更多