【问题标题】:How to wait for an Async function to finish before doing anything?如何在做任何事情之前等待异步函数完成?
【发布时间】:2019-05-31 10:36:56
【问题描述】:

我正在使用登录 API 登录我的应用程序,并且从登录 API 获得的响应中,我想调用另一个 API 来填充主页上的数据。

但是,当我尝试进行第二次 API 调用然后转到主页时。它在 API 完成之前移动到第二页并给出空值。 (第二个 API 调用正常工作,并在一段时间后提供 req 数据)

我该如何解决这个问题?谢谢你。

我的登录页面

import .....

class Login extends StatefulWidget{

  final void Function(UserCredentials) onSignedIn;

  @override
  _LoginState createState() => _LoginState();
}

class _LoginState extends State<Login> {

  var response;

  //To save data from  FIRST API to shared Pref
  Future<bool> saveNamedPreference(String ID, String authid) async {

    SharedPreferences prefs = await SharedPreferences.getInstance();

    prefs.setString("ID", ID );
    prefs.setString("authID", authid );

    return await prefs.setBool("iDExist", true);
  }


  //
  //To save data from  SECOND API to shared Pref
  Future<bool> saveUserPreference(String name, String role) async {

    SharedPreferences prefs = await SharedPreferences.getInstance();

    prefs.setString("name", name);
    prefs.setString("role", role );

    return await prefs.setBool("UserExists", true);
  }


  @override
  Widget build(BuildContext context){

    //SECOND API CALL 
    Future<int> saveUserDetails(String userID, String authID) async{

      getUser(userID, authID).then((value){

        final json = value;
        if(json!="Error"){
          User user = userFromJson(json);
          saveUserPreference(user.username, user.role);
          print('set the other values too ');
          return 1;
        }
        else{
          print('dint get proper json data ');
          return 0;
        }
      });

    }

    //LOGIN API 
    Future<Map<String, dynamic>> getData() async {
      var client = http.Client();


      var response = await client
          .post(
          Uri.encodeFull(
              '{url}'),
          body:
        {"email":"$username","password":"$password"}

      ).whenComplete(
          client.close);

      var res = json.decode(response.body);

      if(response.statusCode <200 || response.statusCode > 400){
        print("Error");
         throwError();
      }
      if(response.statusCode == 200 ){

        saveNamedPreference(res["userId"], res["id"]);;
        UserCredentials uc = userCredentialsFromJson(response.body);

//Using then so that it shifts to Home only after func completion however its not happening 
        saveUserDetails(uc.userId, uc.id).then((value){
          widget.onSignedIn(uc); //gives call back to root page to move to HOME 
        });
      }

      if (!mounted)
        return {'success': false};

      return json.decode(response.body);
    }
;

    Stack stack = Stack(
      ...... );

    return Scaffold(
        resizeToAvoidBottomPadding: false,
      body: stack
    );
  }
}

在我的主页中,在 init 方法中,我从 Shared Pref 访问值(使用相同的 async then 方法),然后使用 setState 更新值,但它仍然给出 null 值。

【问题讨论】:

    标签: flutter


    【解决方案1】:

    首先,将所有这些带有 api 调用的方法移到您的 build 方法之外。

    也许问题就在这里: saveNamedPreference(res["userId"], res["id"]);

    您无需等待此方法返回。 当您使用异步方法并想要等待响应时,您需要使用 await。

    我觉得这段代码看起来好多了……

    import .....
    
    class Login extends StatefulWidget {
    
      final void Function(UserCredentials) onSignedIn;
    
      @override
      _LoginState createState() => _LoginState();
    }
    
    class _LoginState extends State<Login> {
      var response;
    
      //To save data from  FIRST API to shared Pref
      Future<bool> saveNamedPreference(String ID, String authid) async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
    
        prefs.setString("ID", ID);
        prefs.setString("authID", authid);
    
        return await prefs.setBool("iDExist", true);
      }
    
      //To save data from  SECOND API to shared Pref
      Future<bool> saveUserPreference(String name, String role) async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
    
        prefs.setString("name", name);
        prefs.setString("role", role);
    
        return await prefs.setBool("UserExists", true);
      }
    
      //SECOND API CALL 
      Future<int> saveUserDetails(String userID, String authID) async {
        final json = await getUser(userID, authID);
    
        if (json != "Error") {
          User user = userFromJson(json);
          saveUserPreference(user.username, user.role);
          print('set the other values too ');
          return 1;
        } else {
          print('dint get proper json data ');
          return 0;
        }
      }
    
      //LOGIN API 
      Future<Map<String, dynamic>> getData() async {
        var client = http.Client();
    
        var response = await client
            .post(
            Uri.encodeFull('{url}'),
            body: {"email": "$username", "password": "$password"}
        );
    
        var res = json.decode(response.body);
    
        if (response.statusCode < 200 || response.statusCode > 400) {
          print("Error");
          throwError();
        }
    
        if (response.statusCode == 200) {
          await saveNamedPreference(res["userId"], res["id"]);
          UserCredentials uc = userCredentialsFromJson(response.body);
    
          //Using then so that it shifts to Home only after func completion however its not happening 
          await saveUserDetails(uc.userId, uc.id);
          widget.onSignedIn(uc); //gives call back to root page to move to HOME
        }
    
        if (!mounted) {
          return {'success': false};
        }
    
        return json.decode(response.body);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            resizeToAvoidBottomPadding: false,
            body: _buildStack(),
        );
      }
    
      Widget _buildStack(){
        return Stack(
          ......
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 2019-06-17
      • 1970-01-01
      • 2020-03-02
      • 1970-01-01
      相关资源
      最近更新 更多