بنقرة واحدة
add-non-reentrant
Add non-reentrant protection to prevent a Cubit method from running multiple times simultaneously
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Add non-reentrant protection to prevent a Cubit method from running multiple times simultaneously
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Add custom error handling with catchError to a mix() call for logging, error conversion, or suppression
Add internet connectivity checking before executing a Cubit method with optional retry
Add debounce to delay method execution until after a period of inactivity for search or validation
Add EffectQueue to state for triggering multiple sequential one-time UI effects
Add Effect fields to state class for one-time UI notifications like snackbars, navigation, or form clearing
Add error state handling to widgets using context.isFailed() and context.getException()
| name | add-non-reentrant |
| description | Add non-reentrant protection to prevent a Cubit method from running multiple times simultaneously |
This skill prevents a Cubit method from running multiple times simultaneously.
Adds the nonReentrant parameter to a mix() call so that:
This is equivalent to droppable() from the bloc_concurrency package, but for Cubit methods.
Ask the user which Cubit method needs non-reentrant protection, or identify methods that:
Add nonReentrant: nonReentrant to the mix() call:
import 'package:bloc_superpowers/bloc_superpowers.dart';
class UserCubit extends Cubit<User> {
UserCubit() : super(User());
void loadData() => mix(
key: this,
nonReentrant: nonReentrant, // Add this line
() async {
final user = await api.loadUser();
emit(user);
},
);
}
With nonReentrant:
// User taps "Load" button rapidly 3 times
cubit.loadData(); // ✓ Executes
cubit.loadData(); // ✗ Ignored (first still running)
cubit.loadData(); // ✗ Ignored (first still running)
// First call completes
cubit.loadData(); // ✓ Executes (previous call finished)
Prevent duplicate API calls:
void loadProducts() => mix(
key: this,
nonReentrant: nonReentrant,
() async {
final products = await api.getProducts();
emit(state.copyWith(products: products));
},
);
Combine for robust data loading:
void loadData() => mix(
key: this,
nonReentrant: nonReentrant,
retry: retry,
() async {
final data = await api.getData();
emit(data);
},
);
Prevent double-submit:
void submitForm(FormData data) => mix(
key: this,
nonReentrant: nonReentrant,
() async {
await api.submit(data);
emit(state.copyWith(submitted: true));
},
);
Allow concurrent operations for different items, but prevent duplicate operations on the same item:
void processItem(String itemId) => mix(
key: this,
nonReentrant: nonReentrant(key: (ProcessItem, itemId)),
() async {
await api.processItem(itemId);
},
);
With this setup:
processItem('A') and processItem('B') can run concurrentlyprocessItem('A') called twice rapidly: second call is ignoredvoid deleteItem(String id) => mix(
key: (DeleteItem, id), // State tracking per item
nonReentrant: nonReentrant, // Inherits key from mix
() async {
await api.deleteItem(id);
emit(state.copyWith(
items: state.items.where((i) => i.id != id).toList(),
));
},
);
| Feature | Behavior |
|---|---|
nonReentrant | Drops duplicate calls while running |
sequential | Queues calls and processes one at a time |
Use nonReentrant when:
Use sequential when:
Good candidates:
Not recommended:
sequential instead)class ProductCubit extends Cubit<ProductState> {
ProductCubit() : super(const ProductState());
// Prevent duplicate loads
void loadProducts() => mix(
key: this,
nonReentrant: nonReentrant,
retry: retry,
() async {
final products = await api.getProducts();
emit(state.copyWith(products: products));
},
);
// Prevent double-delete on same item
void deleteProduct(String id) => mix(
key: (DeleteProduct, id),
nonReentrant: nonReentrant,
() async {
await api.deleteProduct(id);
emit(state.copyWith(
products: state.products.where((p) => p.id != id).toList(),
));
},
);
// Prevent double-submit
void checkout() => mix(
key: Checkout,
nonReentrant: nonReentrant,
() async {
final order = await api.checkout(state.cart);
emit(state.copyWith(order: order, cart: []));
},
);
}