async_guard 0.0.1 copy "async_guard: ^0.0.1" to clipboard
async_guard: ^0.0.1 copied to clipboard

Prevent duplicate async calls, handle loading & errors in one line. Safe lifecycle, double-tap protection, and clean API for Flutter.

async_guard

Prevent duplicate async calls, handle loading & errors in one line.
No more boilerplate. No more bugs. Just guard it.

pub version Dart 3 Flutter License: MIT


What is this? #

async_guard is a lightweight utility that wraps any async call with production-ready protections β€” in a single line:

  • πŸ›‘οΈ Duplicate prevention β€” block concurrent calls with the same ID
  • ⏳ Loading state β€” one callback, automatic start/stop
  • 🚨 Error handling β€” built-in try-catch, no boilerplate
  • ⏱️ Timeout support β€” auto-cancel long-running tasks
  • 🧬 Lifecycle safe β€” guards against setState after dispose
  • πŸ”˜ GuardedButton β€” drop-in widget with double-tap protection & loading indicator
  • πŸͺ„ Extension syntax β€” chain .guard() on any Future

Every Flutter developer writes the same 15 lines of loading/error/duplicate boilerplate. async_guard replaces all of it with one function call.


Getting Started #

Installation #

dependencies:
  async_guard: ^0.0.1
flutter pub get

Minimal Example #

import 'package:async_guard/async_guard.dart';

// That's it. Errors caught, duplicates blocked.
final result = await guard(() => api.login());

Usage #

Basic #

final result = await guard(() => api.login());

If login() throws, the error is caught. If the same call is already running, the duplicate is ignored.

With loading state #

await guard(
  () => api.login(),
  onLoading: (isLoading) => setState(() => loading = isLoading),
);

onLoading(true) fires before execution, onLoading(false) fires after β€” regardless of success or failure.

With error handling #

await guard(
  () => api.login(),
  onError: (e) => showSnackBar('Failed: $e'),
);

Full example #

final user = await guard<User>(
  () => api.login(email, password),
  id: 'login',
  onLoading: (v) => setState(() => isLoading = v),
  onSuccess: (user) => navigateTo('/home'),
  onError: (e) => showSnackBar('Error: $e'),
  timeout: Duration(seconds: 10),
);

GuardedButton #

A drop-in widget that handles everything automatically:

GuardedButton(
  onTap: () => api.submit(data),
  child: Text('Submit'),
)
  • βœ… Disables itself while running
  • βœ… Shows a loading indicator
  • βœ… Prevents double-tap
  • βœ… Zero configuration needed

Customize the loading indicator:

GuardedButton(
  onTap: () => api.submit(data),
  loadingIndicator: CircularProgressIndicator(color: Colors.white),
  style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
  child: Text('Submit'),
)

Extension Syntax #

Chain .guard() on any Future:

final token = await api.login(email, password).guard(id: 'login');

With callbacks:

await api.login(email, password).guard(
  id: 'login',
  onLoading: (v) => setState(() => loading = v),
  onError: (e) => showError(e),
);

Lifecycle-Safe Async #

Prevent setState after dispose crashes:

@override
void initState() {
  super.initState();
  safeAsync(this, () async {
    final data = await api.fetchData();
    setState(() => _data = data);
  });
}

Or use the extension on State:

this.runSafe(() async {
  final data = await api.fetchData();
  setState(() => _data = data);
});

API Reference #

guard<T>() #

Parameter Type Default Description
task Future<T> Function() β€” The async function to execute
id String? auto Unique ID for duplicate prevention
onLoading void Function(bool)? β€” Loading state callback
onSuccess void Function(T)? β€” Success callback
onError void Function(Object)? β€” Error callback
timeout Duration? β€” Max execution duration
preventDuplicate bool true Block concurrent duplicate calls

safeAsync() #

Parameter Type Description
state State The widget's State object
task Future<void> Function() The async function to run
onError void Function(Object)? Error callback (lifecycle-safe)

GuardedButton #

Parameter Type Default Description
onTap Future<void> Function() β€” Async callback on press
child Widget β€” Button content
loadingIndicator Widget? β€” Custom loading widget
disabledWhileLoading bool true Disable button while running
style ButtonStyle? β€” Optional button style

Extensions #

Extension On Method Description
GuardExtension<T> Future<T> .guard() Same params as guard<T>()
SafeAsyncExtension State .runSafe() Shorthand for safeAsync(this, task)

Why This Package? #

Flutter async code is repetitive and error-prone:

// ❌ What you write today β€” every single time
bool _isLoading = false;

Future<void> _submit() async {
  if (_isLoading) return;           // prevent double tap
  setState(() => _isLoading = true);
  try {
    await api.submit();
  } catch (e) {
    showError(e);
  } finally {
    if (mounted) {
      setState(() => _isLoading = false);
    }
  }
}
// βœ… With async_guard
await guard(
  () => api.submit(),
  id: 'submit',
  onLoading: (v) => setState(() => _isLoading = v),
  onError: (e) => showError(e),
);

15 lines β†’ 5 lines. No bugs, no forgetting mounted, no duplicate calls.


Architecture #

lib/
 β”œβ”€β”€ async_guard.dart          ← Barrel export
 └── src/
      β”œβ”€β”€ guard.dart           ← Core guard() function
      β”œβ”€β”€ guard_manager.dart   ← Singleton task tracker
      β”œβ”€β”€ safe_async.dart      ← Lifecycle-safe async helpers
      β”œβ”€β”€ guarded_button.dart  ← Double-tap-proof button widget
      └── extensions.dart      ← Future<T>.guard() extension

Zero dependencies beyond Flutter SDK. Lightweight, tree-shakeable, and fully tested.


Requirements #

Requirement Version
Dart SDK >=3.0.0 <4.0.0
Flutter >=3.10.0
Null safety βœ…
Dependencies None (Flutter SDK only)

πŸ’– Support #

If this package helps you build better Flutter apps, consider supporting the development:

Support on SociaBuzz

Your support helps keep this package maintained and up-to-date. Every contribution is greatly appreciated! πŸ™


License #

MIT β€” see LICENSE for details.

5
likes
160
points
34
downloads

Documentation

Documentation
API reference

Publisher

verified publisherridltech.my.id

Weekly Downloads

Prevent duplicate async calls, handle loading & errors in one line. Safe lifecycle, double-tap protection, and clean API for Flutter.

Repository (GitHub)
View/report issues

Topics

#async #guard #loading #button #state-management

Funding

Consider supporting this project:

sociabuzz.com

License

MIT (license)

Dependencies

flutter

More

Packages that depend on async_guard