Rules / Suspicious / avoid-passing-async-when-sync-expected
avoid-passing-async-when-sync-expected
lint/suspicious/avoid-passing-async-when-sync-expectedrecommended
Same as avoid-passing-async-when-sync-expected · Dart Code MetricsFlags an async function literal passed where a synchronous callback is
expected.
When a parameter's type is a function that does not return a Future,
passing an async closure hands back a Future the caller never awaits: the
body runs out of order, its exceptions escape as unhandled errors rather than
being caught, and any value it produces is silently lost. Pass a synchronous
closure, or widen the parameter to a Future-returning function if
asynchronous work is genuinely intended. Detection matches positional call
arguments against the parameter types of functions and methods declared in
the same file.
Invalid
example.dartdart
// Bad: passing async function to sync parameter
void processSync(void Function() callback) {
callback();
}
void example() {
processSync(() async {
await Future.delayed(Duration(seconds: 1));
print('Done');
});
}
class Handler {
void setup(void Function(String) handler) {
handler('test');
}
void badSetup() {
setup((value) async {
await processAsync(value);
});
}
}
void executeCallback(String Function(int) fn) {
print(fn(42));
}
void misuse() {
executeCallback((n) async {
await delay();
return '$n';
});
}
// More violations
void performAction(void Function(String, int) callback) {
callback('test', 42);
}
void badAction() {
performAction((name, count) async {
await Future.delayed(Duration(milliseconds: 100));
print('$name: $count');
});
}
class DataLoader {
void loadData(String Function() fetcher) {
final data = fetcher();
print(data);
}
void loadBad() {
loadData(() async {
await Future.delayed(Duration(seconds: 1));
return 'data';
});
}
}
Avoid passing an async function where a synchronous callback is expected
6void example() {
7 processSync(() async {
∙
Avoid passing an async function where a synchronous callback is expected
18 void badSetup() {
19 setup((value) async {
∙
Avoid passing an async function where a synchronous callback is expected
29void misuse() {
30 executeCallback((n) async {
∙
Avoid passing an async function where a synchronous callback is expected
41void badAction() {
42 performAction((name, count) async {
∙
Avoid passing an async function where a synchronous callback is expected
54 void loadBad() {
55 loadData(() async {
∙
Valid
example.dartdart
// Good: passing sync function to sync parameter
void processSync(void Function() callback) {
callback();
}
void example() {
processSync(() {
print('Done');
});
}
class Handler {
void setup(void Function(String) handler) {
handler('test');
}
void goodSetup() {
setup((value) {
processSync(value);
});
}
}
void executeCallback(String Function(int) fn) {
print(fn(42));
}
void goodUse() {
executeCallback((n) {
return '$n';
});
}
// OK: async callback passed to async parameter
void processAsync(Future<void> Function() callback) async {
await callback();
}
void asyncToAsync() {
processAsync(() async {
await Future.delayed(Duration(seconds: 1));
print('Done');
});
}
// OK: extracting async logic separately
void separated(void Function() callback) {
callback();
}
void _asyncWork() async {
await Future.delayed(Duration(seconds: 1));
}
void extract() {
separated(() {
_asyncWork(); // fire and forget (or capture result)
});
}
// Good: passing sync callbacks to sync parameters
void performAction(void Function(String, int) callback) {
callback('test', 42);
}
void goodAction() {
performAction((name, count) {
print('$name: $count');
});
}
// Good: using named function for sync callback
class DataLoader {
String _fetchData() {
return 'data';
}
void loadData(String Function() fetcher) {
final data = fetcher();
print(data);
}
void loadGood() {
loadData(_fetchData);
}
}
// Good: sync arrow function
void processItems(void Function(String) handler) {
handler('item');
}
void goodProcess() {
processItems((item) => print('Processing: $item'));
}
How to configure
Set the severity of avoid-passing-async-when-sync-expected in your falcon.json:
falcon.jsonjson
{
"linter": {
"rules": {
"suspicious": {
"avoid-passing-async-when-sync-expected": "error"
}
}
}
}