onRequest<Request, Response> method
EventSubscription
onRequest<Request, Response>(
- RequestHandler<
Request, Response> handler, { - int priority = Priority.normal,
- String? identifier,
Register a handler for request/response communication.
When request<Request, Response>(...) is called with a matching
(Request, Response) type pair (and, optionally, identifier),
handlers walk in descending priority. Each handler may:
- Return a non-null value to claim the call; dispatch stops there.
- Return
nullto concede so the next handler can claim. - Throw to signal a real error; the chain stops and the exception propagates to the caller unchanged. Subsequent handlers do not run.
Concession by null works whether or not Response is nullable.
null is the framework's "I won't answer" signal. Throws are
reserved for genuine errors. See request for how the consumer
observes the all-conceded case (it depends on which method they
call).
Returns an EventSubscription for cancellation.
Example:
final sub = bus.onRequest<SearchQuery, SearchResults>((env) async {
final hit = await tryProvider(env.event);
return hit; // null to let the next provider try
}, priority: 10);
Implementation
EventSubscription onRequest<Request, Response>(
RequestHandler<Request, Response> handler, {
int priority = Priority.normal,
String? identifier,
}) {
_checkNotDisposed();
final key = (Request, Response);
final buckets =
_requestHandlers.putIfAbsent(
key,
_RequestBuckets<Request, Response>.new,
)
as _RequestBuckets<Request, Response>;
final List<_RequestEntry<Request, Response>> list = identifier == null
? buckets.general
: buckets.byId.putIfAbsent(
identifier,
() => <_RequestEntry<Request, Response>>[],
);
final entry = _RequestEntry<Request, Response>(
priority: priority,
run: handler,
);
list.add(entry);
if (identifier == null) {
buckets.markGeneralDirty();
} else {
buckets.markIdDirty(identifier);
}
return _EventHandlerSub(
onCancel: () {
list.remove(entry);
if (list.isEmpty) {
if (identifier == null) {
if (buckets.byId.isEmpty) _requestHandlers.remove(key);
} else {
buckets.removeIdBucket(identifier);
if (buckets.byId.isEmpty && buckets.general.isEmpty) {
_requestHandlers.remove(key);
}
}
}
},
);
}