Erica ross
Erica ross

Reputation: 99

Error handling an http request result in flutter

I am trying to handle an error given when logging in to check if the user and password are correct through an http request, the problem is that even though I handle the error it still enters the welcome screen because my method to check always ends up in true because I am error handling the information incorrectly.I want the user to be able to see the error, yet my code only shows me the exception. https://dart.dev/guides/libraries/futures-error-handling I looked here, yet for my specific situation I didn't find the answer.

prefix0.Error err = prefix0.Error();
  Future<bool> check(User user) async {
    final userResponse = await ApiClient.signIn(user).catchError((error) {
      //TODO: handle errors
      err.message = jsonDecode(error.toString())["message"];
      throw("some arbitrary error");
    });
    // TODO: Guardar el token en sharedpreferences y verificar si se logro

    return true;
  }

I really just want to show the user what his error is instead of myself (meaning that throw will not work since it just stops the code, and taking it out will just make the return true always be true.

Upvotes: 1

Views: 7167

Answers (2)

Abion47
Abion47

Reputation: 24661

There are two ways to handle this. First, let the exception bubble to the location in your screen code that you are calling the network method. Surround that location with a try/catch to catch the exception and handle it there:

// Network Class
Future check(User user) async {
  final userResponse = await ApiClient.signIn(user);
  // TODO: Guardar el token en sharedpreferences y verificar si se logro

  return userResponse;
}

// Screen Class
void someMethod() async {
  ...
  try {
    final userResponse = Network.check(userData);
    // TODO: Handle the user response
  } catch (e) {
    String errorMessage = e.toString();
    // TODO: Do something with the error message, such as show a snackbar:
    Scaffold.of(context).showSnackbar(Snackbar(
      content: Text(errorMessage),
    ));
  }
}

The other is to have a UserResponse class that contains the response data and has an error state for when the response doesn't succeed. The screen code can then detect this state and respond appropriately:

// Network Class
Future<UserResponse> check(User user) async {
  final userResponse = await ApiClient.signIn(user)
      .then((data) => UserResponse.fromNetworkResponse(data))
      .catchError((error) => UserResponse.fromError(error));

  // TODO: Guardar el token en sharedpreferences y verificar si se logro

  return userResponse;
}

// Screen Class
void someMethod() async {
  ...
  final userResponse = Network.check(userData);
  if (userResponse.hasError) {
    String errorMessage = userResponse.errorMessage;
    // TODO: Do something with the error message, such as show a snackbar:
    Scaffold.of(context).showSnackbar(Snackbar(
      content: Text(errorMessage),
    ));
  } else {
    // TODO: Handle the user response
  }
}

The second method takes a little bit of setup, but it's the most flexible and doesn't require you to rely on a try/catch to function.

Upvotes: 0

Paras Nath Chaudhary
Paras Nath Chaudhary

Reputation: 876

You should not return the value at the last line. You should return true only when the Future completes with a value i.e. return tru in .then() callback as shown below:

Future<bool> check(User user) async {
final userResponse = await ApiClient.signIn(user)
    .then((value){
        // TODO: handle value
        return true;
    })
    .catchError((error) {
      //TODO: handle errors
      err.message = jsonDecode(error.toString())["message"];
      throw("some arbitrary error");
    });
    return false;
}

Upvotes: 6

Related Questions