Function 异步函数依次返回两个不同的结果

Function 异步函数依次返回两个不同的结果,function,flutter,dart,asynchronous,async-await,Function,Flutter,Dart,Asynchronous,Async Await,我已经编写了一个异步颤振/飞镖函数,在我看来它的行为出人意料。以下代码结构: static Future<bool> verifySometing() async { try { await getCloudData().then((snapshot) { if (snapshot.exists && snapshot.hasData) { bool dataValid = await validateDat

我已经编写了一个异步颤振/飞镖函数,在我看来它的行为出人意料。以下代码结构:

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,然后返回false:

Data is correct
Something went wrong

这与我想知道的关于Dart中函数的任何事情都是背道而驰的,因为我总是假设一旦触发了return,函数就完成了。你知道这是怎么发生的吗?

问题在于这一行

await getCloudData().then((snapshot) {
在这里,您不仅添加了
wait
ing,还附加了
then
回调。所以实际上,无论返回什么,都是
回调
函数的返回值,即
(快照){}

您需要传递到
中的回调函数,然后
将该
返回true
并将其作为
等待
的结果提供给我们

所以,如果你把

var bool = await getCloudData().then((snapshot) { ..... });
那么这个
bool
,就等于
true
。就这样。没有从主函数返回

换成这个,

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

希望,我能解释清楚。

你的假设中有一些错误

首先,您将
附加到
getCloudData()
返回的future。这意味着您不是在等待
getCloudData()
,而是等待
getCloudData()返回的额外未来。然后(…)
,当传递给它的回调函数完成时,该未来将返回。(除非第一个future抛出错误,否则将调用回调。)

其次,回调函数在自己的作用域上运行。因此,这段代码并没有执行您认为它正在执行的操作:

booldatavalid=wait validateData(snapshot.data);
如果(数据有效){
打印(“数据正确”);
返回true;
}
此返回将影响回调函数,而不是
verifySomething
函数

鉴于上述情况,操作顺序如下:

  • validateMething
    函数
    wait
    s
    getCloudData()。然后(…)
  • getCloudData()
    被调用
  • getCloudData()
    返回,然后调用传递给
    的回调
  • (假设快照有数据)
    validateData
    被调用
  • (假设数据已成功验证)打印“数据正确”,回调函数返回
    true
  • validateMething
    被通知等待的未来已完成,因此继续执行
  • “出错”被打印出来,并且
    validateMething
    函数返回
    false
  • 一般来说,当混合
    async/await
    then
    模式时,这类错误很常见。除非您知道自己在做什么,否则请坚持其中之一,最好是
    async/await
    模式。例如,重构代码以消除对
    then
    的调用,如下所示:

    static Future verifySometing()异步{
    试一试{
    最终快照=等待getCloudData();
    if(snapshot.exists&&snapshot.hasData){
    bool dataValid=wait validateData(snapshot.data);
    如果(数据有效){
    打印(“数据正确”);
    返回true;
    }
    }
    }捕获(e){
    打印('Error$e');
    返回false;
    }
    打印(“出了问题”);
    返回false;
    }
    

    既然没有麻烦的闭包需要处理,
    return
    将按预期从
    validateMething
    返回,您不需要处理回调和范围之类的问题。

    请记住,当您使用
    wait
    时,您不需要使用
    then
    ,反之亦然。另外,
    await
    停止代码的执行,同时释放线程用于其他工作,并且仅在等待的工作完成时继续。与
    不同,后者不会停止下面代码的执行。
    
    var snapshot = await getCloudData();
    if (snapshot.exists && snapshot.hasData) {
      bool dataValid = await validateData(snapshot.data);
      if (dataValid) {
        print('Data is correct');
        return true;
      }
    }