【一起学Rust | 框架篇 | Tauri2.0框架】rust和前端的相互调用(前端调用rust)

news2024/12/25 2:14:37

在这里插入图片描述

文章目录

    • 前言
    • 1. 前端调用rust(command)
      • 1. 在后端定义一个`command`
      • 2. 注册`command`
      • 3. 前端调用`command`
    • 2. 前端调用rust(event)
    • 4. command完整实例


前言

本期将继续接着上一期,继续探索tauri中rust和前端的相互调用,上一期我们介绍了rust调用前端,这一期我们继续探索前端调用rust。

首先还是回忆一下上周tauri的前后端通信示意图

tauri事件机制

从该图片我们可以清晰的看出来,tauri的前端和rust后端通信是通过事件机制来实现的,在上期中,我介绍了事件机制的基础,以及如何通过rust的工具来调用前端的方法,也就是触发前端监听的事件。

这张图是双向的,也就是说前端也可以触发rust监听的事件,这样前端也可以调用rust的方法,这也是本期的主要内容。

除此以外,tauri官方推荐的前端调用rust后端的主要方法是通过command来调用,因此,如果你要做的东西比较简单,那么更建议使用command来调用,因为command的调用方式更简单,更符合前端开发者的习惯,而且选择合适的使用场景的能力对于一个开发人员来说也是非常重要的。

Command通信示意图

从图上可以看出,tauri的command其实与fetch api是非常相似的,都是请求、响应的模式,但其实这个机制是使用json-rpc来实现的(这些都是官方写的),不过这个不需要深究,除非你是老专家。我们只需要知道怎么用的,置于原理那是后面的事情,如果tauri可以活到那个时候的话。

以上是tauri使用command来与rust后端通信的流程图。其中一些转换方法tauri已经为我们实现了,当你理解了这张图,在使用command时就会非常简单。

Because this mechanism uses a JSON-RPC like protocol under the hood to serialize requests and responses, all arguments and return data must be serializable to JSON.

注意:本文内容均可在官方文档中找到对应内容: https://v2.tauri.app/concept/inter-process-communication/

1. 前端调用rust(command)

为了更加方便的描述tauri是如何从前端调用rust的,我先写一个流程,然后以这个流程来逐步实现该功能。

  1. 在rust后端定义一个command
  2. 注册command
  3. 前端调用command

1. 在后端定义一个command

在rust中,command的定义非常简单,只需要在src-tauri/src/main.rs中定义一个函数,并使用tauri::command!宏来标记该函数为command即可,就像程序自带的command,greet就是这么做的(学习就是在看例子)。

#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

在这个greet的例子中,可以看到,name是需要传入的参数,然后返回一个格式化的字符串。(不写分号等于返回,不需要写return)
那么在这里需要注意的是参数,也就是tauri如何接受参数,根据官方文档,传入参数可以是任意类型,但是前提是这个类型必须实现serde::Deserialize

注意:参数是可以重命名的,类似于后端开发中的dto,但是需要使用#[tauri::command(rename_all = "snake_case")]来标记,否则tauri会报错。这样前端就可以传入与后端参数名一样了。

返回值必须是String,因为要序列化(其实可以返回任何类型,但是你的类型必须实现serde::Serialize,如果是传入参数,那么必须实现serde::Deserialize,个人建议这两个序列化和反序列化的特征全部实现,就不用考虑那么多了,如果你比较仔细,就可以在这仔细看看)。

初次以外还可以返回数组buffer,可以用(tauri::ipc::Response),错误处理也可使用Result,本文章不可能做到面面俱到,读者应学会看官方文档,当然在后续文章中我应该也是会补上的。

注意:

  1. 其实你也可以把command放在lib.rs,拆分开这样代码才会更加条理。
  2. command是唯一的,不允许重复,也就是说,你得注意命名规范,避免重复。

2. 注册command

在定义完command之后,我们需要将command注册到tauri中,这样tauri才能知道我们定义了哪些command,前端才能调用这些command

src-tauri/src/main.rs中,我们可以看到tauri::Builder的实例,我们可以在这个实例上调用invoke_handler方法来注册command

tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![greet])

这是官方案例中的greet方法,我们只需要学习其使用方法就可以了,可以直接跟在greet后面(那是个数组),或者替换也没关系,就像下面这样

tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![greet, another_command])

这样就可以注册多个command了。

3. 前端调用command

在tauri 2.0中,tauri导出了invoke方法,因此我们导入该方法以后调用即可。

// 导入 invoke 方法
import { invoke } from '@tauri-apps/api/core';

// ...
invoke('my_custom_command'); //调用 command

注意:tauri官方推荐使用异步command,但是经我自己测试是有问题的,异步command执行不了异步方法(笑死)。

2. 前端调用rust(event)

使用事件来进行通信与上期内容是差不多的。在前端中,tauri导出了emit方法,我们导入这个方法就可以触发rust中的监听器。

// 导入 emit 方法
import { emit } from '@tauri-apps/api/event';

// ...
emit('my_custom_event', payload); //触发事件

其中,payload是传递给rust的参数,是个对象。

然后在rust中监听这个事件

use tauri::Listener;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    .setup(|app| {
      app.listen("my_custom_event", |event| {
        if let Ok(payload) = serde_json::from_str::<DownloadStarted>(&event.data) {
          println!("downloading {}", payload.url);
        }
      });
      Ok(())
    })
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

注意:你甚至可以用前端监听事件,触发事件,简直非常好用。

发挥你的想象力,如果你想要监听指定webview的事件,那么也是可以实现的

use tauri::{Listener, Manager};

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    .setup(|app| {
      let webview = app.get_webview_window("main").unwrap();
      webview.listen("logged-in", |event| {
        let session_token = event.data;
        // save token..
      });
      Ok(())
    })
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

官方文档内容非常多,如果看完这些你还存在问题,那么请看官方文档,或者者在下方留言。

4. command完整实例

在rust中定义command

struct Database;

#[derive(serde::Serialize)]
struct CustomResponse {
  message: String,
  other_val: usize,
}

async fn some_other_function() -> Option<String> {
  Some("response".into())
}

#[tauri::command]
async fn my_custom_command(
  window: tauri::Window,
  number: usize,
  database: tauri::State<'_, Database>,
) -> Result<CustomResponse, String> {
  println!("Called from {}", window.label());
  let result: Option<String> = some_other_function().await;
  if let Some(message) = result {
    Ok(CustomResponse {
      message,
      other_val: 42 + number,
    })
  } else {
    Err("No result".into())
  }
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    .manage(Database {})
    .invoke_handler(tauri::generate_handler![my_custom_command])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

然后在前端中调用

import { invoke } from '@tauri-apps/api/core';

// Invocation from JavaScript
invoke('my_custom_command', {
  number: 42,
})
  .then((res) =>
    console.log(`Message: ${res.message}, Other Val: ${res.other_val}`)
  )
  .catch((e) => console.error(e));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2078718.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视觉SLAM十四讲-理论到实践课程作业笔记-第六讲-光流法和直接法

CH6_No1&#xff1a; 1-1. 光流法可分为哪几类? 答&#xff1a;正向和逆向&#xff0c;其中两种方法各又包含了直加法和组合法&#xff1b; 1-2 在 compositional 中,为什么有时候需要做原始图像的 wrap?该 wrap 有何物理意义? 答&#xff1a;我个人的理解此处的wrap就是…

大数据系统测试——大数据系统解析(下)

各位好&#xff0c;我是 道普云 欢迎关注我的主页 希望这篇文章对想提高软件测试水平的你有所帮助。 学习和理解大数据系统每一个层次需要解决的技术问题和对应的一些技术需求是对大数据系统进行软件测试的一个基础&#xff0c;上篇文章里我们已经跟大家分享了数据收集层、…

33.python socket

python socket编程 概念说明心跳包的作用基于以上知识的基础上我们来实现一个代码socket serversocket client执行结果 概念说明 socket传输数据是基于字节流的&#xff0c;默认情况下是无边界的字节流。 一般情况下数据里中包含心跳包和数据包。数据包就是我们实际需要发送给…

中国建筑轮廓数据

建筑轮廓数据是建筑的边界矢量数据&#xff0c;一般该数据属性中会记录对应建筑的高度或者楼层数&#xff0c;通过建筑轮廓数据置顶的高程字段拉伸&#xff0c;就可以得到建筑白盒模型&#xff0c;所以&#xff0c;我们在各类导航地图中看到的白盒模型&#xff0c;实际上是建筑…

深度剖析:医疗行业财务报表的核心要素与解析策略

在当今医疗行业中&#xff0c;财务报表分析扮演着至关重要的角色。医疗机构需要通过对财务数据的准确分析来做出关键决策&#xff0c;管理资源&#xff0c;改善效率&#xff0c;并确保最终提供高质量的医疗服务。本文将深入探讨医疗行业中财务报表分析的重要性、关键指标和分析…

《一种个性化逻辑定制与类置换方案》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

通过违法app发现大量网站被挂黑页

免责声明&#xff1a;文章来源于真实事件&#xff0c;关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一…

AI搜索的商业模式困境:Perplexity从拒绝广告到高价广告的转变

随着人工智能技术的发展&#xff0c;AI搜索逐渐成为人们日常生活中不可或缺的一部分。在这个领域&#xff0c;Perplexity曾被认为是AI搜索领域的领军企业&#xff0c;以其强大的智能搜索能力脱颖而出。然而&#xff0c;随着OpenAI的SearchGPT发布在即&#xff0c;Perplexity似乎…

掌握结构型模式——全景回顾

在前几篇文章中&#xff0c;我们详细探讨了多种结构型设计模式&#xff0c;今天来进行一个大总结——结构型设计模式主要关注类与对象的组合和组织&#xff0c;确保我们能够构建出稳固、灵活且易于维护的软件系统。无论你是初学者还是有经验的开发者&#xff0c;这篇文章都会帮…

计算循环冗余码(CRC)--软考笔记

1、什么是CRC循环冗余码&#xff08;CRC&#xff09; CRC&#xff08;Cyclic Redundancy Check&#xff09;是一种用于检测数据传输错误的校验码。它通过一个预定义的生成多项式来计算一个固定长度的校验值&#xff0c;这个值被附加到原始数据上一起发送。接收端使用相同的生成…

二叉树 - 完全二叉树的节点个数

222. 完全二叉树的节点个数 方法一&#xff1a;递归 /*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val (valundefined ? 0 : val)* this.left (leftundefined ? null : left)* this.right (rightundefined ? nul…

多商户2.3.0后台顶部添加修改密码修复方法

问题&#xff1a;后台登录不能修改自己的密码&#xff1b; 解决方法&#xff1a; 修改前端代码&#xff0c;文件路径&#xff08;平台后台&#xff0c;商户后台一样的修改方法&#xff09;&#xff1a;src/layout/navBars/breadcrumb/user.vue 修改第一处 代码&#xff1a; 修…

IM即时通讯给娱乐社交、游戏等行业带来了什么影响?看这篇就知道

企业IM即时通讯技术的发展和应用&#xff0c;对我们的生活、工作、沟通和交流带来了显著的影响和改变。 IM即时通讯技术的发展不仅改变了我们的沟通方式&#xff0c;还提高了工作效率&#xff0c;促进了团队协作&#xff0c;保障了信息安全&#xff0c;并推动了业务创新。随着技…

机器人学导论之连杆参数

目录 一、连杆参数[1] 二、将下肢看作二连杆结构 三、参考文献 一、连杆参数[1] 1.1关节角 绕轴&#xff0c;从旋转到的角度。 备注&#xff1a;从z轴正方向看&#xff0c;顺时针为正&#xff0c;逆时针为负。 图 1 平面三连杆操作臂 以图1为例子&#xff0c; 表示…

文献解读-农业-第二十九期|《β-淀粉酶和磷脂酸参与板栗种子萌发》

关键词&#xff1a;农业&#xff1b;基因测序&#xff1b;变异检测&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;Beta-amylase and phosphatidic acid involved in recalcitrant seed germination of Chinese chestnut标题&#xff08;中文&#xff09…

岩土工程中的渗流问题:有限单元法的理论与实践

有限单元法在岩土工程问题中应用非常广泛&#xff0c;很多商业软件如Plaxis/Abaqus/Comsol等都采用有限单元解法。尽管各类商业软件使用方便&#xff0c;但其使用对用户来说往往是一个“黑箱子”。相比而言&#xff0c;开源的有限元程序计算方法透明、计算过程可控&#xff0c;…

宝藏!盟主自控独家讲义:《掌中宝》(精卫篇)1-9章:甄选部分

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;盟主自控独家讲义&#xff1a;《掌中宝》(精卫篇)。 Part1&#xff1a;资料封面&目录 Part2&#xff1a;资料各个章节具体内容 自控专属数学基础储备 第1章 自动控制的基本概念 第2章 控制系统的数学模型 第3章…

8.26算法训练

1.八皇后 Checker Challenge 输入&#xff1a; 6输出&#xff1a; 2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4是以前寒假写过的题目&#xff0c;所以有的影响&#xff0c;大致思路就是用深度遍历然后判断是否在对角线上就ok了&#xff0c;有大概思路的话&#xff0c; 还是不难的…

比特币的签名和验证(基于ECDSA)

比特币&#xff08;Bitcoin&#xff09;和以太坊&#xff08;Ethereum&#xff09;等区块链技术使用了加密算法来确保交易的安全性。私钥签名和公钥验证是这些算法的核心部分&#xff0c;主要用于证明交易的发起者拥有交易中使用的资金的控制权&#xff0c;而不需要暴露私钥本身…

【开源分享】java+swing+mysql简单学生信息管理系统设计与实现

个人主页&#xff1a;程序员杨工 个人简介&#xff1a;从事软件开发多年&#xff0c;前后端均有涉猎&#xff0c;具有丰富的开发经验 博客内容&#xff1a;全栈开发&#xff0c;分享Java、Python、Php、小程序、前后端、数据库经验和实战 文末有本人名片&#xff0c;希望和大家…