Tauri provides a simple yet powerful command system for calling Rust functions from your web app.
Commands can accept arguments and return values. They can also return errors and be async.
Arguments should be passed as a JSON object with camelCase keys:
Arguments can be of any type, as long as they implement serde::Deserialize.
Please note, when declaring arguments in Rust using snake_case, the arguments are converted to camelCase for JavaScript.
To use snake_case in JavaScript, you have to declare it in the tauri::command statement:
If your handler could fail and needs to be able to return an error, have the function return a Result:
If the command returns an error, the promise will reject, otherwise, it resolves:
As mentioned above, everything returned from commands must implement serde::Serialize, including errors.
This can be problematic if you’re working with error types from Rust’s std library or external crates as most error types do not implement it.
In simple scenarios you can use map_err to convert these errors to Strings:
Since this is not very idiomatic you may want to create your own error type which implements serde::Serialize. In the following example, we use the thiserror crate to help create the error type. It allows you to turn enums into error types by deriving the thiserror::Error trait. You can consult its documentation for more details.
A custom error type has the advantage of making all possible errors explicit so readers can quickly identify what errors can happen. This saves other people (and yourself) enormous amounts of time when reviewing and refactoring code later.
It also gives you full control over the way your error type gets serialized. In the above example, we simply returned the error message as a string, but you could assign each error a code similar to C, this way you could more easily map it to a similar looking TypeScript error enum for example.
Asynchronous functions are benefical in Tauri to perform heavy work in a manner that doesn’t result in UI freezes or slowdowns.
If your command needs to run asynchronously, simply declare it as async.
When working with borrowed types, you have to make additional changes. These are your two main options:
Option 1: Convert the type, such as &str to a similar type that is not borrowed, such as String. This may not work for all types, for example State<'_, Data>.
Example:
Option 2: Wrap the return type in a Result. This one is a bit harder to implement, but should work for all types.
Use the return type Result<a, b>, replacing a with the type you wish to return, or () if you wish to return nothing, and replacing b with an error type to return if something goes wrong, or () if you wish to have no optional error returned. For example:
Result<String, ()> to return a String, and no error.
Result<(), ()> to return nothing.
Result<bool, Error> to return a boolean or an error as shown in the Error Handling section above.
The tauri::generate_handler! macro takes an array of commands. To register
multiple commands, you cannot call invoke_handler multiple times. Only the last
call will be used. You must pass each command to a single call of
tauri::generate_handler!.