-2

I want to extract the value of the response from an api call.

  import 'package:http/http.dart' as http;

  refreshToken() {
  Future<http.Response> _response = _httpClient.callApi(
      endPoint: refreshTokenEndpoint, variables: refreshTokenVariables);

  http.Response _tokenResponse;
  _response.then((http.Response value) => _tokenResponse = value);

  print(_tokenResponse.body);
  }

But when i try to access the body i get an error body was called on null.

Abiud Orina
  • 1,162
  • 8
  • 19

3 Answers3

0

You need wait for _tokenResponse because come from Future.

refreshTokenSolution() async {
    Future<bool> _response = Future.delayed(Duration(seconds: 2), () => true);
    bool _tokenResponse = await _response; // Wait this response and after go next line
    print(_tokenResponse); //TRUE
  }
0

You need to use async/await with your methods to get the values.

you can do the following

Future<void> refreshToken() async {
  final http.Response _response = await _httpClient.callApi(
    endPoint: refreshTokenEndpoint,
    variables: refreshTokenVariables,
  );

  print(_response.body);
}

The reason that yours will not work is because you are not awaiting the call. You have the right idea, you just need to specify in your code that _httpClient.callApi is going to take some time to return a value. When you do that, your code will run asynchronously rather than synchronously. You can read more here.

When you run your code this is what is happening

void main() async {
  var str = 'this is going to run first';
  // executes immediately
  print(str);
  
  // executes immediately
  // this will waits one second before printing
  Future.delayed(Duration(seconds: 1)).then((_) {
    str = 'this will print third after 1 second of waiting';
    print(str);
  });
  
  // executes immediately
  // this print statement will print second because [Future] has not finished
  // completed the await of the 1 sec duration
  str = 'this is going to print second';
  print(str);
}

Everything is executing immediately but because we have a second delay, its function doesn't get executed after the future has awaited the 1 sec duration.

Therefore, we can see that you are assigning _tokenResponse with the response from your request, but because you are not awaiting the result, your code moves on and your value gets left behind.

mrgnhnt96
  • 3,562
  • 1
  • 17
  • 36
0

There is something called the event loop and every time we call a Future without an await we are not running the code, but also scheduling an event to de resolved in the Future.

import 'package:http/http.dart' as http;

refreshToken() {
  // Here the http is schedulling but it hasn't an answer.
  // That answer or result will be available in the future
  Future<http.Response> _response = _httpClient.callApi(
      endPoint: refreshTokenEndpoint, variables: refreshTokenVariables);

  // Here, you are declaring a _tokenResponse variable with null value.
  http.Response _tokenResponse;

  // Here, you are specifying that when the _response had a result IN THE FUTURE
  // the _tokenResponse will have a assigned value (but in the future,
  // not in the present)
  _response.then((http.Response value) => _tokenResponse = value);

  // _tokenResponse continue being null because _response will
  // be resolved in the Future. Next, _tokenResponse.body is the same
  // call null.body
  print(_tokenResponse.body);
}

_tokenResponse continue being null because _response will be resolved in the Future. Next, _tokenResponse.body is the same call null.body and this generates an error.

Frank Moreno
  • 304
  • 1
  • 7