How to access message in DioError - flutter

How can I access the "Message" field inside the e
My postRequest function:
Future<Response> postRequest(String endPoint, dynamic data) async {
Response response;
try {
if (data != null) {
response = await _dio!.post(endPoint, data: data);
} else {
response = await _dio!.post(endPoint);
}
} catch (e) {
//I can reach the message from here and return it, but this
is not what I want to do.
if (e is DioError) print(e.response);
throw Exception(e);
}
return response;
}
where I want to reach the message:
var response;
try{
response = await http.postRequest("Stok/$type", requestObj);
}catch(e){
print("message....: $e");
}

Future<Response> postRequest(String endPoint, dynamic data) async {
Response response;
try {
if (data != null) {
response = await _dio!.post(endPoint, data: data);
} else {
response = await _dio!.post(endPoint);
}
return response;
} on DioError {
rethrow; // or throw e;
}
}
Now, just call it like that
var response;
try{
response = await http.postRequest("Stok/$type", requestObj);
} on DioError catch(e){
print("message....: ${e.message}");
}

Related

How to get part from JSON using 'response.stream.bytesToString()' instead of "(response.body) ['data']"

Edit 1:
I am new to Flutter, and coding altogether, so please answer in simple terms.
I can get a JSON string from this API: [https://reqres.in/api/users?page=1][1]. using jsonDecode(response.body)
And I can also get specific part within this JSON using
jsonDecode(response.body)['data'] // 'data' is a List[]
But Postman, generates this completely different code to get data from api.
Postman uses response.stream.bytesToString());
Now I want to keep using Postman's auto generated code, but tweek it such that I get only the List, 'data', from the API.
My full code is:
class ApiService {
Future<List<UserModel>> getData() async {
try{
Response response = await get( Uri.parse('https://reqres.in/api/users?page=2'));
List result = await jsonDecode(response.body)['data'];
if (response.statusCode == 200) {
print(response);
print('');
print(response.body);
print('');
print(result);
print('');
return result.map((e) => UserModel.fromJson(e)).toList();
}
else {
print(response.reasonPhrase);
throw Exception(response.reasonPhrase);
}
} catch(e){
print('Error AA gaya \n\n\n $e') ;
throw e;
}
}
}
------------
Postman generated code is:
==========================
var request = http.Request('GET', Uri.parse('https://reqres.in/api/users?page=2'));
a
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
[1]: https://reqres.in/api/users?page=1
your code is correct but the way you parse is wrong
Future<List<UserModel>> getData() async {
try{
Response response = await get( Uri.parse('https://reqres.in/api/users?page=2'));
if (response.statusCode == 200) {
var jdata = jsonDecode(response.body);
print(response);
print('');
print(response.body);
print('');
print(jdata);
print('');
return jdata['data'].map((e) => UserModel.fromJson(e)).toList();
}
else {
print(response.reasonPhrase);
throw Exception(response.reasonPhrase);
}
} catch(e){
print('Error AA gaya \n\n\n $e') ;
throw e;
}
}

Common method for flutter api calls

Is there any example that I can refer to about Common class/method for flutter API calls(GET,POST,...) in flutter? I have handled all the API requests in a common method in react native, I'm not sure how to implement it in flutter.
you have to call getRequest using url parameter
Future<Response> getRequest(String url) async {
Response response;
try {
response = await _dio.get(url,
options: Options(headers: {
HttpHeaders.authorizationHeader:
'Bearer $accessToken'
}));
print('response $response');
} on DioError catch (e) {
print(e.message);
throw Exception(e.message);
}
return response;
}
here is the post method
Future<Response> posRequestImage(String url, data) async {
try {
response = await _dio.post(
url,
data: formData,
options: Options(headers: {
HttpHeaders.authorizationHeader:
'Bearer $accessToken'
}),
);
if (response.statusCode == 200) {
return response;
}
print('post response $response');
} on DioError catch (e) {
print(e.message);
throw Exception(e.response?.statusMessage);
}
return response;
}
You can create a class to handle it. For example, this is my class to handle all service for user model
import 'package:http/http.dart' as http;
class UserService {
var baseUrl = URL.devAddress;
Future<User> getUser() async {
final response = await http.get(
Uri.parse(baseUrl + "user/1")
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
return data
} else {
throw Exception("Failed");
}
}
}
Future<void> getUser(String username) async {
Uri uri = Uri.parse('https://example.com');
try {
Map<String, dynamic> params = new HashMap();
params['username'] = username;
final response = await client.post(uri,
body: jsonEncode(params),
);
print("response ${response.body}");
} on FetchDataException {
throw FetchDataException("No Internet connection");
}
}

Trying to make a request with http in Flutter

I am trying to make a class in Flutter that can send requests to an API and then store the response inside the class, however every time I send a request I get some sort of infinite request that end up in timing out. Here is my code:
When the user press the button in the screen:
onPressed: () async {
print('Email: ${emailFieldController.text} and password: ${passwordFieldController.text}');
await Api.sendRequest('POST', '/session', {
"email": emailFieldController.text,
"password": passwordFieldController.text
});
if (Api.content.containsKey("error")) {
print("Error connectiong with API");
print("The error was:" + Api.content["error"].toString());
} else {
if (Api.content["status"] == 200) {
print("User find");
} else {
print("User not find");
}
}
})
The class that I built:
import 'dart:convert';
import 'package:http/http.dart';
class Api {
static final String baseURL = 'http://192.168.15.4/api/v1';
static Map content;
static Future<void> sendRequest(String method, String endpoint, [Map body, Map headers]) async {
Response response;
switch (method) {
case 'GET':
try {
response = await get('$baseURL' + endpoint);
Api.content = jsonDecode(response.body);
} catch (e) {
Api.content["error"] = e.toString();
}
break;
case 'POST':
try {
response =
await post('$baseURL' + endpoint, body: body, headers: headers);
Api.content = jsonDecode(response.body);
print('Passando depois POST');
} catch (e) {
Api.content["error"] = e.toString();
}
break;
case 'PUT':
try {
response =
await put('$baseURL' + endpoint, body: body, headers: headers);
Api.content = jsonDecode(response.body);
} catch (e) {
Api.content["error"] = e.toString();
}
break;
case 'DELETE':
try {
response = await delete('$baseURL' + endpoint, headers: headers);
Api.content = jsonDecode(response.body);
} catch (e) {
Api.content["error"] = e.toString();
}
break;
}
}
}
I also tried to alter the return type of the method, but got the same result.
So I discovered what was wrong, baseURL attribute was missing the port, so the request never found it's target. So in the and the baseURL value was: http://192.168.15.4:3333/api/v1

How do I return error from a Future in dart?

In my flutter app, I have a future that handles http requests and returns the decoded data. But I want to be able to send an error if the status code != 200 that can be gotten with the .catchError() handler.
Heres the future:
Future<List> getEvents(String customerID) async {
var response = await http.get(
Uri.encodeFull(...)
);
if (response.statusCode == 200){
return jsonDecode(response.body);
}else{
// I want to return error here
}
}
and when I call this function, I want to be able to get the error like:
getEvents(customerID)
.then(
...
).catchError(
(error) => print(error)
);
Throwing an error/exception:
You can use either return or throw to throw an error or an exception.
Using return:
Future<void> foo() async {
if (someCondition) {
return Future.error('FooError');
}
}
Using throw:
Future<void> bar() async {
if (someCondition) {
throw Exception('BarException');
}
}
Catching the error/exception:
You can use either catchError or try-catch block to catch the error or the exception.
Using catchError:
foo().catchError(print);
Using try-catch:
try {
await bar();
} catch (e) {
print(e);
}
You can use throw :
Future<List> getEvents(String customerID) async {
var response = await http.get(
Uri.encodeFull(...)
);
if (response.statusCode == 200){
return jsonDecode(response.body);
}else{
// I want to return error here
throw("some arbitrary error"); // error thrown
}
}
Another way to solve this is by using the dartz package.
An example of how to use it would look something similar like this
import 'package:dartz/dartz.dart';
abstract class Failure {}
class ServerFailure extends Failure {}
class ResultFailure extends Failure {
final int statusCode;
const ResultFailure({required this.statusCode});
}
FutureOr<Either<Failure, List>> getEvents(String customerID) async {
try {
final response = await http.get(
Uri.encodeFull(...)
);
if (response.statusCode == 200) {
return Right(jsonDecode(response.body));
} else {
return Left(ResultFailure(statusCode: response.statusCode));
}
}
catch (e) {
return Left(ServerFailure());
}
}
main() async {
final result = await getEvents('customerId');
result.fold(
(l) => print('Some failure occurred'),
(r) => print('Success')
);
}
You can return the error data like this if you want to read the error object:
response = await dio.post(endPoint, data: data).catchError((error) {
return error.response;
});
return response;
//POST
Future<String> post_firebase_async({String? path , required Product product}) async {
final Uri _url = path == null ? currentUrl: Uri.https(_baseUrl, '/$path');
print('Sending a POST request at $_url');
final response = await http.post(_url, body: jsonEncode(product.toJson()));
if(response.statusCode == 200){
final result = jsonDecode(response.body) as Map<String,dynamic>;
return result['name'];
}
else{
//throw HttpException(message: 'Failed with ${response.statusCode}');
return Future.error("This is the error", StackTrace.fromString("This is its trace"));
}
}
Here is how to call:
final result = await _firebase.post_firebase_async(product: dummyProduct).
catchError((err){
print('huhu $err');
});

How to catch exception in flutter?

This is my exception class. Exception class has been implemented by the abstract exception class of flutter. Am I missing something?
class FetchDataException implements Exception {
final _message;
FetchDataException([this._message]);
String toString() {
if (_message == null) return "Exception";
return "Exception: $_message";
}
}
void loginUser(String email, String password) {
_data
.userLogin(email, password)
.then((user) => _view.onLoginComplete(user))
.catchError((onError) => {
print('error caught');
_view.onLoginError();
});
}
Future < User > userLogin(email, password) async {
Map body = {
'username': email,
'password': password
};
http.Response response = await http.post(apiUrl, body: body);
final responseBody = json.decode(response.body);
final statusCode = response.statusCode;
if (statusCode != HTTP_200_OK || responseBody == null) {
throw new FetchDataException(
"An error occured : [Status Code : $statusCode]");
}
return new User.fromMap(responseBody);
}
CatchError doesn't catch the error when the status is not 200. In short error caught is not printed.
Try
void loginUser(String email, String password) async {
try {
var user = await _data
.userLogin(email, password);
_view.onLoginComplete(user);
});
} on FetchDataException catch(e) {
print('error caught: $e');
_view.onLoginError();
}
}
catchError is sometimes a bit tricky to get right.
With async/await you can use try/catch like with sync code and it is usually much easier to get right.
Let's say this is your function which throws an exception:
Future<void> foo() async {
throw Exception('FooException');
}
You can either use try-catch block or catchError on the Future since both do the same thing.
Using try-catch
try {
await foo();
} on Exception catch (e) {
print(e); // Only catches an exception of type `Exception`.
} catch (e) {
print(e); // Catches all types of `Exception` and `Error`.
}
Use catchError
await foo().catchError(print);
I was trying to find this answer when got to this page, hope it helps: https://stackoverflow.com/a/57736915/12647239
Basicly i was just trying to catch an error message from a method, but i was calling
throw Exception("message")
And in "catchError" i was getting "Exception: message" instead of "message".
catchError(
(error) => print(error)
);
fixed with the return in the above reference
Future < User > userLogin(email, password) async { try {
Map body = {
'username': email,
'password': password
};
http.Response response = await http.post(apiUrl, body: body);
final responseBody = json.decode(response.body);
final statusCode = response.statusCode;
if (statusCode != HTTP_200_OK || responseBody == null) {
throw new FetchDataException(
"An error occured : [Status Code : $statusCode]");
}
return new User.fromMap(responseBody); }
catch (e){
print(e.toString());
}