Function does not continue after catch - flutter

I have a try..catch within a dart function. When the await client.post throws an error, it does not continue after the catch, why?
#override
Future<http.Response> post(url, {Map<String, String?>? headers, body, Encoding? encoding, BuildContext? context}) async {
headers = await prepareHeaders(headers);
http.Response? response = null;
try {
response = await client.post(url, headers: headers as Map<String, String>?, body: body, encoding: encoding);
} catch (_) {
debugPrint('test'); // It comes here
}
// Does not come here
log(url: url, type: 'POST', body: body as String?, response: response!);
return await parse(response, context: context);
}

And it shouldnt. In the code below the catch, you are relying on the response object being set. If the post errors, that wont be the case, producing more errors. Move the log and the return call inside the try block.

Your code almost certainly is continuing after the catch block; it's just immediately throwing another exception. If client.post throws an exception, then response will not be set and will retain its initial value of null. However, after your catch block, you do:
log(url: url, type: 'POST', body: body as String?, response: response!);
which asserts that response is not null. That will throw a TypeError.
I don't know why you aren't observing the TypeError, but I'd suspect that you have a blanket catch block somewhere higher up in the call stack that is swallowing the exception (especially given your use of catch (_) in what code you have shown). This is why Effective Dart recommends:
Avoiding catch without on.
Not catching Errors.

The function will not execute after the catch block, the function will be terminated after the catch whenever any exception occurred then the catch block gets called. To solve this issue you can try this.
#override
Future<http.Response> post(url, {Map<String, String?>? headers, body,
Encoding? encoding, BuildContext? context}) async {
headers = await prepareHeaders(headers);
http.Response? response = null;
try {
response = await client.post(url, headers: headers as Map<String,
String>?, body: body, encoding: encoding);
log(url: url, type: 'POST', body: body as String?, response: response!);
return await parse(response, context: context);
} catch (_) {
debugPrint('test');
rethrow;
}
}

Related

How to catch an Error for timeout on http.client Flutter

I have a Future that calls a POST API using the http.client structure.
At the moment there is an issue with said API and my call is timing out before the full header is received, giving me a unhandled exception.
How is the best way to return this exception and show a snackbar of the issue returned?
Future<dynamic> get() async {
try {
var response = await client.post(
Uri.parse(Url),
headers: headers,
body: body,
);
}
here is the simple http call to catch an Error for timeout
return the error and catch this where from you handle the api call
import 'package:http/http.dart';
Future<dynamic> get() async {
try {
var response = await post(
Uri.parse(Url),
headers: headers,
body: body,
).timeout(Duration(seconds: 2), onTimeout: (){
/// here is the response if api call time out
/// you can show snackBar here or where you handle api call
return Response('Time out!', 500);
});
}catch(e){
print(e);
}
}
you can change your duration in the timeout method

http put did not send any response in flutter

Hey I have this app where I can update status, and I use http.put method, but it takes forever to response. I got this error
error
And here is the code for http.put
Future<void> mapEventToState(
Emitter<ReportStatusState> emit, ReportStatusEvent event) async {
emit(ReportStatusLoading());
ReportStatusPut statusPut = event.statusPutBody;
// ReportStatusModel model =
// await apiAuthRepository.updateReportStatus(statusPut, event.id);
ReportStatusModel model = await updateReportStatus({'biaya': '0', 'status': 'SELESAI'}, event.id);
print(model);
if (!model.success) {
emit(ReportStatusFailure(model.message));
}
print(model.code);
emit(ReportStatusSuccess());
}}
Future<ReportStatusModel> updateReportStatus(
Map data, String id) async {
final SharedPreferencesManager sharedPreferencesManager =
locator<SharedPreferencesManager>();
String? token =
sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessToken);
try {
final response = await http.put(
Uri.parse('https://api.komplekku.com/officer/api/report/v1/$id'),
body: json.encode(data),
headers: {'Authorization': 'Bearer $token'});
return ReportStatusModel.fromJson(json.decode(response.body));
} catch (e) {
throw Exception(e);
}
}
There is nothing wrong with the API, I already check using Postman and it worked perfectly fine, Anyone know what went wrong?

Why sending the following request ends up with uncaught exception?

I have the following Flutter & Dart code function, which sends a request to the server:
Future<void> autoAuth(BuildContext ctx) async {
final url = Uri.parse('${this._baseURL.toString()}/auto-auth');
try {
final deviceStorage = await SharedPreferences.getInstance();
if (deviceStorage.getString('refreshToken') == null) {
return this._setUser(null);
}
final response = await http.post(url, headers: {
'Authorization': 'Bearer ${deviceStorage.getString('refreshToken')!}',
}).timeout(const Duration(seconds: 3));
final Map<String, dynamic> responseBody = json.decode(response.body);
if (responseBody['success']) {
this._refreshAccessToken(ctx, deviceStorage);
return this._setUser(new User(
id: responseBody['data']['id'],
isSubscribed: responseBody['data']['isSubscribed'],
playlistId: responseBody['data']['playlistId'],
));
}
this._setUser(null);
} on SocketException {
this._setUser(null);
throw Error();
} on TimeoutException {
this._setUser(null);
throw Error();
} catch (_) {
this._setUser(null);
}
}
Note, that url is wrong intentionally, so the request will timeout.
But, for this, I coded: .timeout(...) on the future request. So, basically, after 3 secnods it should caught by on TimeoutException exception catch.
It does so. However, after something like 1 minute (probably some default timeout of http request in dart), I get an uncaught exception because the request has timed-out. Where Am I wrong?
This is because you are using it in the wrong way. The .timeout code you use, is generic timeout for any future. Thus, you catch the error of the future timeout, but you don't catch the error being generated from the http request timeout.
To use it correctly, first add the following import: import 'package:http/io_client.dart' as http;
Then change the code to:
final ioClient = HttpClient();
ioClient.connectionTimeout = const Duration(seconds: 3);
final client = http.IOClient(ioClient);
final response = await client.post(url, headers: {
'Authorization': 'Bearer ${deviceStorage.getString('refreshToken')!}',
});

Flutter'sTry Catch never works

I tried everything.. I always have some problem with async try catch blocks..
I read the guide that flutter has on it but nothing there works.. i am trying to make http requests, but whenever there is a problem like (connection refused) it breaks the code. i tried:
try {
switch (type) {
case RequestType.Get:
response = await _httpClient
.get(url, headers: headers)
.catchError(catchError);
break;
case RequestType.Put:
try {
response = await _httpClient
.put(url, body: body, headers: headers)
.catchError(catchError);
} catch (e) {
catchError();
}
break;
case RequestType.Post:
response = await _httpClient
.post(url, body: body, headers: headers)
.catchError(catchError);
break;
default:
return null;
break;
}
} catch (e) {
catchError();
}
I tried every combination there.. with async catchError only.. with try catch only.. with try catch above the switch, with try catch only on the http request.. NOTHING works.. How can this be done????
Keep one try...catch for all, keep it simple:
Future doRequest(type, url, headers) async {
try {
switch (type) {
case RequestType.Get: return await _httpClient.get(url, headers: headers);
case RequestType.Put: return await _httpClient.put(url, body: body, headers: headers);
case RequestType.Post: return await _httpClient.post(url, body: body, headers: headers);
}
throw('Method not supported');
} catch (e) {
// print exception to console
// or comment the line, if You don't care about error
print(e.error);
return null;
}
}
or avoid using try...catch in this logic and handle issue on higher level.
Future doRequest(type, url, headers) {
switch (type) {
case RequestType.Get: return _httpClient.get(url, headers: headers);
case RequestType.Put: return _httpClient.put(url, body: body, headers: headers);
case RequestType.Post: return _httpClient.post(url, body: body, headers: headers);
}
throw('Method not supported');
}
try {
final response = await doRequest(RequestType.Get, "some/url/here", {});
/* do something with response */
}
catch (error) {
//handle error here
}

Unable to use http.post in compute() function

I'm trying to use the compute() function to trigger a top level method that calls an HTTP POST.
I can see the method being executed, but then it just hangs where I do the actual post, with no errors returned.
However if I call this without calling compute, it works fine
uploadData(Map args) {
print("uploading data"); // i see this in the logs
API().uploadData(args["data"], args["user"], args["apikey"]);
}
and it's called via
compute(uploadData, {
"data": dataList,
"user": widget.userProps,
"apikey": widget.apiKey
});
lastly this is my API uploadData method
uploadData(List files, User userdata, String apikey) async {
try {
String sessionid = await _getSession();
String _base = 'http://192.168.2.13:3000/upload';
String body = json.encode({
"api": apikey,
"user": userdata.toMap(),
"data": files,
"sessionid": sessionid
});
print("I AM HERE"); // this is called
await http.post(_base,
body: body, headers: {"Content-Type": "application/json"});
print("this is not called");
} catch (e) {
print("Error"); // no error
print(e);
}
}
you have to return, because API().uploadData returns a future (of null, I assume). If we don't return, API().uploadData is executed and then uploadData(Map args) return null value and pops out of the stack immediate; isolate has no functions, microtask queue or event queue left, it will exit.
uploadData(Map args) {
print("uploading data"); // i see this in the logs
return API().uploadData(args["data"], args["user"], args["apikey"]);
}