async-operations-in-euv[20260804142554]

0 阅读1分钟

euv 中的异步操作

项目代码:github.com/euv-dev/euv

现代 Web 应用本质上是异步的。无论你是从 API 获取数据、从用户设备读取文件,还是等待定时器过期,代码都需要处理在未来某个时刻完成的操作。euv 提供了一套强大的异步原语——包括 spawn_localJsFuture、JSON 处理、Promise 和浏览器 Response 对象——使得在 Web 中编写异步 Rust 代码成为可能。本文将探讨 euv 中所有可用的异步功能。

理解浏览器上下文中的异步

在传统 Rust 应用中,你可能会使用 tokioasync-std 进行异步操作。然而,euv 应用通过 WebAssembly(WASM)在浏览器中运行,浏览器具有单线程事件循环。euv 不使用多线程运行时,而是利用浏览器原生的异步原语——Promise、fetch 和回调——并将它们包装成对 Rust 友好的 API。

euv 中的关键异步原语包括:

  • spawn_local:在浏览器事件循环上生成异步任务。
  • JsFuture:将 JavaScript Promise 包装为 Rust Future
  • JSON 工具:解析和序列化来自 JavaScript 的 JSON 数据。
  • Promise / Response:直接访问浏览器异步 API。

spawn_local —— 生成异步任务

spawn_local 是在 euv 中启动异步任务的主要方式。它在浏览器事件循环上调度一个 future 来运行,类似于 tokio::spawn 在服务端 Rust 中的工作方式。

spawn_local(async {
    // 这段代码异步运行
    let result = some_async_operation().await;
    // 处理结果
});

spawn_local 接收一个 async 块(或任何实现 Future 的类型)并调度它执行。future 将由浏览器事件循环轮询,当它完成时,任何 .await 点都会恢复执行。

spawn_local 的常见用例包括:

  • 数据获取:向 API 发起 HTTP 请求而不阻塞 UI。
  • 定时器:调度延迟或周期性操作。
  • 文件读取:异步读取用户选择的文件。
  • 复杂计算:卸载工作以避免阻塞主线程。

JsFuture —— 将 JavaScript Promise 桥接到 Rust

JsFuture 是一个包装器,将 JavaScript 的 Promise 转换为 Rust 的 Future。这是 JavaScript 异步世界和 Rust async/await 语法之间的桥梁。

当你调用返回 Promise 的浏览器 API(如 fetch)时,可以将结果包装在 JsFuture 中,然后在 Rust 中 .await 它:

let future = JsFuture::from(some_js_promise());
let result = future.await;

JsFuture 实现了标准的 Rust Future trait,因此它可以与 Rust 的 async/await 语法无缝配合,也可以与其他 future 组合使用。

JSON 处理

euv 提供了处理 JSON 数据的工具,JSON 是 Web API 的通用语言。你可以:

  • 解析 JSON:将来自 JavaScript 的 JSON 字符串转换为 Rust 数据结构。
  • 序列化为 JSON:将 Rust 数据结构转换为 JSON 字符串以发送给 API。

JSON 处理对于任何与后端服务器通信的应用都是必不可少的。结合 fetch(通过 JsFuture),你可以构建完整的数据获取管线:

  1. 使用浏览器的 fetch API 发起 HTTP 请求。
  2. 将生成的 Promise 包装在 JsFuture 中。
  3. 等待响应并提取 JSON 数据。
  4. 将 JSON 解析为 Rust 类型。

Promise 和 Response 对象

euv 提供了对浏览器 PromiseResponse 对象的直接访问,使你能够使用浏览器异步 API 的全部功能。

Promise

Promise 表示一个未来才会可用的值。在 euv 中,你可以创建 Promise、解析它们,并用 .then().catch() 链接它们。

Response

Response 表示 HTTP 请求的结果。它提供了以各种格式访问响应体的方法:

  • .json():将响应体解析为 JSON。
  • .text():将响应体作为纯文本字符串获取。
  • .array_buffer():将响应体作为 ArrayBuffer 获取,用于二进制数据。

JsFuture 结合使用时,你可以等待 Response 然后提取数据:

let response = JsFuture::from(fetch(url)).await;
let json_data = JsFuture::from(response.json()).await;

从 API 获取数据

Web 应用中最常见的异步操作之一是从 REST API 获取数据。在 euv 中,这涉及:

  1. 使用浏览器的 fetch 函数发起 HTTP 请求。
  2. 将生成的 Promise 包装在 JsFuture 中。
  3. 等待响应并提取数据。

以下是通用模式:

spawn_local(async {
    let response = JsFuture::from(fetch("https://api.example.com/data")).await;
    // 处理响应
    let data = JsFuture::from(response.json()).await;
    // 使用数据更新信号
});

fetch 函数可通过浏览器 Window 对象使用,euv 提供了对该对象的访问。

异步代码中的错误处理

异步操作可能因多种原因失败:网络错误、服务器错误、超时、数据格式错误等。正确的错误处理对于良好的用户体验至关重要。

在 euv 中,你使用 Rust 的标准错误处理机制来处理异步错误:

  • Result:大多数异步操作返回 Result 类型。使用 match? 运算符处理成功和失败情况。
  • unwrap_or_default():对于失败时可以使用默认值的操作。
  • 信号更新:更新错误状态信号以在 UI 中显示错误消息。
spawn_local(async {
    let result = some_async_operation().await;
    match result {
        Ok(data) => {
            // 更新成功状态
        }
        Err(error) => {
            // 更新错误状态
        }
    }
});

组合多个异步操作

通常,你需要同时或按顺序执行多个异步操作。euv 支持这两种模式:

顺序执行

只需一个接一个地 .await 每个操作:

let first = operation_one().await;
let second = operation_two(first).await;

并发执行

使用 Rust 的 join! 宏或 FuturesUnordered 同时运行多个 future:

let (result1, result2) = futures::join!(operation_one(), operation_two());

异步与响应式信号

euv 异步系统的真正威力在于将其与响应式信号结合使用。你可以:

  1. 在开始异步操作之前设置加载状态信号。
  2. 使用 spawn_local 生成异步任务。
  3. 在操作完成时更新数据或错误信号。
let shared_text: Signal<String> = use_signal(|| "Type here...".to_string());

spawn_local(async {
    // 执行异步工作
    let result = fetch_data().await;
    // 用结果更新信号
    shared_text.set(result);
});

这种模式在异步操作进行时保持 UI 响应,并在数据到达时自动更新 UI。

实践示例:带异步数据的温度转换器

考虑一个从天气 API 获取当前温度的温度转换器:

watch!(celsius, |celsius_value: f64| {
    fahrenheit.set(celsius_value * 9.0 / 5.0 + 32.0);
});

你可以扩展此模式以从 API 获取初始温度:

spawn_local(async {
    let response = JsFuture::from(fetch("https://api.weather.com/temperature")).await;
    let data = JsFuture::from(response.json()).await;
    // 解析并设置初始摄氏度值
});

watch! 宏确保每当摄氏度值变化时(无论是来自 API 还是用户输入),华氏度值都会自动更新。

总结

euv 提供了一套全面的异步原语,用于构建现代 Web 应用:

  • spawn_local:在浏览器事件循环上生成异步任务。
  • JsFuture:将 JavaScript Promise 包装为 Rust Future。
  • JSON 工具:解析和序列化 JSON 数据。
  • Promise / Response:直接访问浏览器异步 API。
  • 错误处理:使用 Resultmatch? 的标准 Rust 错误处理。
  • 信号集成:从异步回调中更新响应式信号。

通过掌握这些异步原语,你可以构建能够与 API 通信、处理用户文件并执行复杂异步操作的 euv 应用——同时保持 UI 响应性,代码干净且可维护。


项目代码:github.com/euv-dev/euv