Async Callback interfaces
Callback interfaces and foreign traits can expose methods which are asynchronous. A toy example here:
#![allow(unused)] fn main() { #[uniffi::export(with_foreign)] #[async_trait::async_trait] trait MyFetcher { async get(url: String) -> String; } fetch_with_fetcher(url: String, fetcher: Arc<dyn MyFetcher>) -> String { fetcher.fetch(url).await } }
Used from Typescript:
class TsFetcher implements MyFetcher {
async get(url: string): Promise<string> {
return await fetch(url).text()
}
}
fetchWithFetcher("https://example.com", new TsFetcher());
You can see this in action in the futures
fixture.
Task cancellation
When the Rust Future is completed, it is dropped, and Typescript is informed. If the Future is dropped before it has completed, it has been cancelled. uniffi-bindgen-react-native
can use this information to call the async callback to cancel, using the standard AbortController
and AbortSignal
machinery.
uniffi-bindgen-react-native
generates an optional argument for each async callback method, which is an options bag containing an AbortSignal
.
It is up to the implementer of each method whether they want to use it or not.
Using exactly the same MyFetcher
trait from above, this example passes the signal straight to the fetch
API.
class TsFetcher implements MyFetcher {
async get(url: string, asyncOptions?: { signal: AbortSignal }): Promise<string> {
return await fetch(url, asyncOptions).text()
}
}
fetchWithFetcher("https://example.com", new TsFetcher());