Skip to content

Instantly share code, notes, and snippets.

@alanleite
Created November 24, 2022 16:44
Show Gist options
  • Save alanleite/527722da3301eb609632ccec2dc5e6be to your computer and use it in GitHub Desktop.
Save alanleite/527722da3301eb609632ccec2dc5e6be to your computer and use it in GitHub Desktop.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart';
import 'package:native_http/native_http.dart';
import 'package:crypto/crypto.dart';
class DebounceHttpClient extends BaseClient {
DebounceHttpClient(
this.httpClient, {
required this.duration,
});
final Client httpClient;
final Duration duration;
final Map<String, Timer?> _timers = {};
final Map<String, Completer<StreamedResponse>> _completers = {};
Future<void> _onSend(
String hash,
BaseRequest request,
) async {
final response = await httpClient.send(request);
final data = await response.stream.toBytes();
// from now, a request can have multiple listeners
_completers[hash]!.complete(
StreamedResponse(
Stream.fromIterable([data]).asBroadcastStream(),
response.statusCode,
contentLength: response.contentLength,
request: request,
headers: response.headers,
isRedirect: response.isRedirect,
persistentConnection: response.persistentConnection,
reasonPhrase: response.reasonPhrase,
),
);
}
@override
Future<StreamedResponse> send(BaseRequest request) {
// based on body, we should create a separed debounce experience
final hash = _generateHash(request as Request);
var completer = _completers[hash] ?? Completer();
var timer = _timers[hash];
completer = (completer.isCompleted) ? Completer() : completer;
timer?.cancel();
timer = Timer(duration, () => _onSend(hash, request));
_completers[hash] = completer;
_timers[hash] = timer;
return completer.future;
}
String _generateHash(Request request) =>
md5.convert(utf8.encode(request.body)).toString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment