Macro zng_app::async_app_hn
source · macro_rules! async_app_hn { ($($tt:tt)+) => { ... }; }
Expand description
Declare an async clone-move app event handler.
The macro input is a closure with optional clone-move variables, internally it uses async_clmv_fn!
so
the input is the same syntax.
The handler generates a future for each event, the future is polled immediately if it does not finish it is scheduled
to update in on_pre_update
or on_update
depending
on if the handler was assigned to a preview event or not.
Note that this means propagation
can only be meaningfully stopped before the
first .await
, after, the event has already propagated.
§Examples
The example declares an async event handler for the CLICK_EVENT
.
CLICK_EVENT.on_event(async_app_hn!(|_, _| {
println!("Clicked Somewhere!");
task::run(async {
println!("In other thread!");
}).await;
println!("Back in UI thread, in an app update.");
})).perm();
The closure input is A, Box<dyn AppWeakHandle>
for all handlers and A
is ClickArgs
for this example. Note that
if you want to use the event args you must annotate the input type, the context and handle types are inferred.
The handle can be used to unsubscribe the event handler, if unsubscribe
is called the handler
will be dropped some time before the next event update. Running tasks are not canceled by unsubscribing, the only way to cancel
then is by returning early inside the async blocks.
CLICK_EVENT.on_event(async_app_hn!(|args: ClickArgs, handle| {
println!("Clicked {}!", args.target);
task::run(async move {
handle.unsubscribe();
});
})).perm();
Internally the async_clmv_fn!
macro is used so you can clone-move variables into the handler.
let status = var("pending..".to_txt());
CLICK_EVENT.on_event(async_app_hn!(status, |args: ClickArgs, _| {
status.set(formatx!("processing {}..", args.target));
task::run(async move {
println!("do something slow");
}).await;
status.set(formatx!("finished {}", args.target));
})).perm();
// can still use after:
let text = status;
In the example above only a clone of status
is moved into the handler. Note that handlers always capture by move, if status
was not
listed in the clone-move section it would not be available after the handler is created. See async_clmv_fn!
for details.
§Futures and Clone-Move
You may want to always clone-move captures for async handlers, because they then automatically get cloned again for each event. This needs to happen because you can have more then one handler task running at the same type, and both want access to the captured variables.
This second cloning can be avoided by using the async_hn_once!
macro instead, but only if you expect a single event.