等待未来函数完成其执行

Posted

技术标签:

【中文标题】等待未来函数完成其执行【英文标题】:Wait for a future function to complete its execution 【发布时间】:2020-10-11 06:15:30 【问题描述】:

我是 Flutter 新手,在下面的代码中,第 18 行调用了读取数据函数(它执行 Firebase 数据库操作)我希望 readData() 函数必须先完成其执行转到打印语句(第 19 行)并进一步执行。

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/cupertino.dart';
import 'package:udharibook/Screens/SignInPage.dart';
import 'package:udharibook/Screens/UserProfile.dart';
import 'package:udharibook/Screens/dashboard.dart';

class AuthService  
  bool flag = false;
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final DBRef = FirebaseDatabase.instance.reference().child('Users');

    handleAuth()
    return StreamBuilder(
      stream: FirebaseAuth.instance.onAuthStateChanged,
      builder: (BuildContext, snapshot) 
        if(snapshot.hasData) 
         readData();
          print(flag);
          if(flag ==true)
            return DashboardPage();
          else
            return UserProfile();
        
        else 
          return SignIn();
        
      ,
    );
  

  Future<void> readData() async 
    final FirebaseUser user = await _auth.currentUser();
    final userid = user.uid;
    DBRef.child(userid).once().then((DataSnapshot data)
      print(userid);
      if(data.value!=null)
        
          flag =  true;
          print(data.key);
          print(data.value);
        
      else
        print('User not found');
        flag = false;
      
    );
  

  signOut()
    FirebaseAuth.instance.signOut();
  

  signIn(AuthCredential authCreds)
    FirebaseAuth.instance.signInWithCredential(authCreds);
  

  signInWithOTP(smsCode,verId)
    AuthCredential authCreds = PhoneAuthProvider.getCredential(
        verificationId: verId,
        smsCode: smsCode
    );
    signIn(authCreds);
  

【问题讨论】:

【参考方案1】:

由于 readData() 是一个 AsyncFunction

在 readData() 之前添加关键字 await ,将强制 readData() 完成,然后打印,但是你不能这样做,因为 StreamBuilder正在等待 Widget 返回类型。

所以你能做的是 . 也许修改您的 readData 以返回 Future boolean readData() ;

 Future<bool> readData() async 
    final FirebaseUser user = await _auth.currentUser();
    final userid = user.uid;
    DBRef.child(userid).once().then((DataSnapshot data)
      print(userid);
      if(data.value!=null)
        
          print(data.key);
          print(data.value);
          return true;
         
        
      else
        print('User not found');
        return false;
      
    );
  

你叫它:

readData().then((value)

 if (value ==true)
return Widget
else
return Widget;


);

希望对您有所帮助。

【讨论】:

设备屏幕出现错误:构建函数返回 null。违规小部件是:StreamBuilderBuild 函数绝不能返回 null。要返回导致建筑小部件填满可用房间的空白空间,请返回“Container()”【参考方案2】:

如果您希望未来在构建/构建器方法中完成,那么使用FutureBuilder 是一个不错的方法。这样,您可以在未来完成时设置占位符小部件,然后在完成后输出所需的结果。在下面的示例中,我使用了一个圆形进度指示器作为占位符,但您可以使用任何小部件:

return StreamBuilder(
  stream: FirebaseAuth.instance.onAuthStateChanged,
  builder: (BuildContext, snapshot) 
    if(snapshot.hasData) 
      return FutureBuilder(
        future: readData(),
        builder: (context, futureSnapshot) 
          if (!futureSnapshot.hasData) return CircularProgressIndicator();

          print(flag);
          if(flag ==true)
            return DashboardPage();
          else
            return UserProfile();
        
      );
    
    else 
      return SignIn();
    
  ,
);

【讨论】:

这意味着readData 函数存在问题。好像永远不会返回了,能不能先等待DBRef.child,然后在下面插入一个return语句return Future.value() 通过返回 Future.value 进一步的代码变成了死代码并再次执行循环进度条

以上是关于等待未来函数完成其执行的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Futures:等待侦听器至少完成一次

等待两个异步完成函数完成,然后再执行下一行代码

如何将任务委托给主线程并等待其执行完成?

如何等待递归直到函数完成执行

等待 Completable 未来线程完成的推荐方法是啥

在自我执行之前等待函数完成