بنقرة واحدة
add-fresh
Add freshness caching to prevent redundant method executions within a time period
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Add freshness caching to prevent redundant method executions within a time period
التثبيت باستخدام 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-fresh |
| description | Add freshness caching to prevent redundant method executions within a time period |
This skill adds freshness caching to prevent redundant method executions within a time period.
Adds the fresh parameter to a mix() call so that:
Ask the user which Cubit method needs freshness caching, or identify methods that:
Add fresh: fresh to the mix() call:
import 'package:bloc_superpowers/bloc_superpowers.dart';
class UserCubit extends Cubit<User> {
UserCubit() : super(User());
void loadData() => mix(
key: this,
fresh: fresh, // Add this line (default: 1 second)
() async {
final user = await api.loadUser();
if (user == null) throw UserException('Failed to load user');
emit(user);
},
);
}
The default freshness period is 1 second. Customize based on how often data changes:
void loadData() => mix(
key: this,
fresh: fresh(freshFor: 5.sec), // Data valid for 5 seconds
() async {
final user = await api.loadUser();
emit(user);
},
);
fresh // 1 second (default)
fresh(freshFor: 5.sec) // 5 seconds
fresh(freshFor: 30.sec) // 30 seconds
fresh(freshFor: 5.minutes) // 5 minutes
fresh(freshFor: 1.hours) // 1 hour
Allow bypassing freshness with a parameter:
void loadData({bool force = false}) => mix(
key: this,
fresh: fresh(
freshFor: 5.sec,
ignoreFresh: force, // When true, ignores freshness
),
() async {
final data = await api.getData();
emit(data);
},
);
// Normal call - respects freshness
cubit.loadData();
// Force refresh - ignores freshness
cubit.loadData(force: true);
Track freshness separately for different parameters:
void loadUser(String userId) => mix(
key: this, // State tracking uses UserCubit
fresh: fresh(
key: (UserCubit, userId), // Freshness tracked per userId
freshFor: 5.sec,
),
() async {
final user = await api.loadUser(userId);
emit(state.copyWith(users: {...state.users, userId: user}));
},
);
With this setup:
context.isWaiting(UserCubit) shows loading for any usercubit.loadData(); // ✓ Executes, data loaded, marked fresh
// ... 2 seconds later (within 5 sec freshness) ...
cubit.loadData(); // ✗ Skipped, data still fresh
// ... 4 more seconds later (total 6 sec, past freshness) ...
cubit.loadData(); // ✓ Executes, data reloaded
If the method fails, freshness is not set. This allows immediate retry:
cubit.loadData(); // ✗ Fails with error
cubit.loadData(); // ✓ Executes immediately (not marked fresh due to error)
Prevent reloading when navigating back to a screen:
void loadScreenData() => mix(
key: this,
fresh: fresh(freshFor: 30.sec),
() async {
final data = await api.getScreenData();
emit(data);
},
);
void loadProducts({bool force = false}) => mix(
key: this,
fresh: fresh(freshFor: 1.minutes, ignoreFresh: force),
() async {
final products = await api.getProducts();
emit(state.copyWith(products: products));
},
);
// In widget
RefreshIndicator(
onRefresh: () => cubit.loadProducts(force: true),
child: ProductList(),
)
void loadData() => mix(
key: this,
fresh: fresh(freshFor: 10.sec),
retry: retry,
() async {
final data = await api.getData();
emit(data);
},
);
void loadData() => mix(
key: this,
fresh: fresh(freshFor: 5.sec),
nonReentrant: nonReentrant,
retry: retry,
() async {
final data = await api.getData();
emit(data);
},
);
Clear freshness manually when needed:
// Clear freshness for a specific key
Superpowers.removeFreshKey(UserCubit);
Superpowers.removeFreshKey((UserCubit, userId));
// Clear all freshness keys
Superpowers.removeAllFreshKeys();
Use cases for manual clearing:
Good candidates:
Consider freshness duration:
Not recommended:
class ProductCubit extends Cubit<ProductState> {
ProductCubit() : super(const ProductState());
// Products stay fresh for 1 minute
void loadProducts({bool force = false}) => mix(
key: this,
fresh: fresh(freshFor: 1.minutes, ignoreFresh: force),
retry: retry,
() async {
final products = await api.getProducts();
emit(state.copyWith(products: products));
},
);
// Product details fresh per product ID
void loadProductDetails(String productId) => mix(
key: (ProductDetails, productId),
fresh: fresh(freshFor: 30.sec),
() async {
final details = await api.getProductDetails(productId);
emit(state.copyWith(
productDetails: {...state.productDetails, productId: details},
));
},
);
}
Ask the user: