I have a text field to search for cities. When I type a character, a request is sent to the server (API). When I enter any character. I need to cancel the previous request that is pending. Please help dear professionals, Thank you). I can't cancel my previous request
this is httpService
Future<http.Response> httpGetPublic(path) async {
try {
var response = await http.get(Uri.parse(path), headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.hostHeader: API.hostname,
HttpHeaders.cacheControlHeader: "no-cache",
HttpHeaders.acceptHeader: "application/json",
HttpHeaders.acceptEncodingHeader: "gzip, deflate, br",
}).timeout(
const Duration(seconds: 30),
onTimeout: () {
return http.Response('Connection Timeout', 408);
},
);
return response;
} catch (error) {
return http.Response('{"error":"${error.toString()}"}', 500);
}
}
this method for fetching data
void fetchData(String query) async {
cities.clear();
_isLoading.value = true;
final response = await httpGetPublic("${API.cities}?name=$query");
try {
Iterable data = jsonDecode(utf8.decode(response.bodyBytes));
if (response.statusCode == 200) {
List<FlightCitiesModel> res = List<FlightCitiesModel>.from(
data.map((model) => FlightCitiesModel.fromJson(model)));
cities.addAll(res);
} else {
if (response.statusCode < 430) {
snackBarResponseError(responseData);
}
}
} catch (error) {
debugPrint("ERROR ====>");
debugPrint(error.toString());
}
_isLoading.value = false;
}
this is my search TextField
TextField(
autofocus: true,
decoration: InputDecoration(
isDense: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
suffixIcon: const Icon(
Icons.search,
size: 26,
),
),
onChanged: (String value) {
if (value.length > 1) {
citiesController.setLoading();
}
if (_timer?.isActive ?? false) _timer!.cancel();
_timer = Timer(const Duration(milliseconds: 150), () {
citiesController.fetchData(value);
});
},
);
You can achieve this using http package's CancelToken
feature along with dio package:
http
and dart:async
.import 'dart:async';
import 'package:http/http.dart' as http;
// Create a variable to hold the current request
http.CancelToken? _cancelToken;
// Modify your existing function to accept a cancel token
Future<http.Response> httpGetPublic(String path) async {
// Cancel the previous request if it exists
_cancelToken?.cancel();
// Create a new cancel token for this request
_cancelToken = http.CancelToken();
try {
var response = await http.get(
Uri.parse(path),
headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.hostHeader: API.hostname,
HttpHeaders.cacheControlHeader: "no-cache",
HttpHeaders.acceptHeader: "application/json",
HttpHeaders.acceptEncodingHeader: "gzip, deflate, br",
},
// Pass the cancel token to the request
cancelToken: _cancelToken,
).timeout(
const Duration(seconds: 30),
onTimeout: () {
// Handle timeout
return http.Response('Connection Timeout', 408);
},
);
return response;
} catch (error) {
return http.Response('{"error":"${error.toString()}"}', 500);
}
}
Now when ever you call this method, it will first cancel the existing request and then calls a new one.