'Future.then must return a value of the returned future's type
I'm continuously getting this error
Unhandled Exception: Invalid argument(s) (onError): The error handler of Future.then must return a value of the returned future's type
NetworkApi
class NetworkApi {
NetworkApi(this.url);
final String url;
Future getData() async {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String data = response.body;
return jsonDecode(data);
} else {
if (kDebugMode) {
print(response.statusCode);
}
}
}
}
ApiSelector
class ApiSelector {
Future getApiData({String categoryName = ""}) async {
late NetworkApi _api;
if(categoryName != ""){
_api = NetworkApi('api');
}else{
_api = NetworkApi('myapi');
}
var Data = await _api.getData();
if (Data['status'] == 'error') {
throw'Error while fetching data';
}
return MyModel.fromJson(Data);
}
}
MyFunction To Call API selector
Future getDataFromApi() async {
await _apiSelector
.getApiData(categoryName: "Some Category")
.then((value) {
myModel = value as MyModel;
print(myModel);
return value;
} ,onError: (error) {
print(error);
return error;
},);
}
I have tried everything to solve this issue. May you please guide me what to do. I have even tried with exception handling but still getting this error.
Solution 1:[1]
Specify the Future of return type like Future<dynamic>
NetworkApi
class NetworkApi {
NetworkApi(this.url);
final String url;
Future<dynamic> getData() async {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String data = response.body;
return jsonDecode(data);
} else {
if (kDebugMode) {
print(response.statusCode);
}
}
}
}
ApiSelector
class ApiSelector {
Future<MyModel> getApiData({String categoryName = ""}) async {
late NetworkApi _api;
if(categoryName != ""){
_api = NetworkApi('api');
}else{
_api = NetworkApi('myapi');
}
var Data = await _api.getData();
if (Data['status'] == 'error') {
throw'Error while fetching data';
}
return MyModel.fromJson(Data);
}
}
MyFunction To Call API selector
Future<MyModel?> getDataFromApi() async {
try {
var value = await _apiSelector.getApiData(categoryName: "Some Category");
myModel = value as MyModel;
return myModel;
} catch(error) {
print(error);
return error;
}
}
Solution 2:[2]
The problem is in getDataFromApi:
Future getDataFromApi() async {
await _apiSelector
.getApiData(categoryName: "Some Category")
.then((value) {
myModel = value as MyModel;
print(myModel);
return value;
} ,onError: (error) {
print(error);
return error;
},);
}
As explained by the error message, your onError handler fails to return the same type as returned by Future.then's success path. (See https://stackoverflow.com/a/66397222/ for an explanation.) This normally would be a compile-time error but ends up being a runtime one because getDataFromApi is declared to return a Future (equivalent to Future<dynamic> instead of Future<MyModel>.
Using the raw Future API with error callbacks (whether with Future.then's onError argument or with Future.catchError) is rather confusing to use directly. You're already using await, so there's no reason for you to be using Future.then. With await, you can use try-catch instead, which makes the problem much clearer:
Future<MyModel> getDataFromApi() async {
try {
var myModel = await _apiSelector.getApiData(categoryName: "Some Category");
print(myModel);
return myModel;
} catch (error) {
print(error);
return error; // WRONG: This is not a `MyModel`!
}
}
To fix this, either your catch block needs to return a MyModel or must throw an exception.
Solution 3:[3]
class ApiSelector {
Future getApiData({String categoryName = ""}) async {
late NetworkApi _api;
if(categoryName != ""){
_api = NetworkApi('api');
}else{
_api = NetworkApi('myapi');
}
var Data = await _api.getData();
if (Data['status'] == 'error') {
//I had to replace throw with Future.value Now All Errors are gone.
return Future.value( 'Error while fetching data');
}
return MyModel.fromJson(Data);
}
}
I hope this will also help others who will face this kind of error sometime in future.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 |
