#web-apps #web-api #browser #tokio #web-worker #async #glue

tokio_with_wasm

在网页浏览器上模拟tokio功能

15个不稳定版本 (3个重大变更)

0.6.1 2024年6月15日
0.6.0 2024年6月15日
0.5.3 2024年6月11日
0.4.5 2024年5月24日
0.3.2 2023年11月8日

#151 in Web编程

Download history 12916/week @ 2024-04-23 13111/week @ 2024-04-30 13172/week @ 2024-05-07 12297/week @ 2024-05-14 6066/week @ 2024-05-21 5977/week @ 2024-05-28 11638/week @ 2024-06-04 13105/week @ 2024-06-11 10728/week @ 2024-06-18 9651/week @ 2024-06-25 12930/week @ 2024-07-02 15970/week @ 2024-07-09 18883/week @ 2024-07-16 19109/week @ 2024-07-23 19140/week @ 2024-07-30 20886/week @ 2024-08-06

每月下载量:80,275

MIT许可证

43KB
557

tokio_with_wasm

Crates.io Documentation License

Recording

使用Rinf测试

tokio_with_wasm是一个为网页浏览器设计的Rust库,提供了tokio的功能。它旨在为Web应用提供与tokio完全相同的特性,利用JavaScript网页API。

这个库由模拟真实tokio行为的JavaScript粘合代码组成。由于tokio_with_wasm没有自己的运行时并且适应JavaScript事件循环,所以tokio的高级特性可能无法正常工作。

当使用spawn_blocking()时,会自动调整网页工作线程的数量以适应并行任务的数量。请参阅文档以获取更多信息。

此库假定您使用wasm-packwasm-bindgen编译Rust项目,目前使用的是wasm32-unknown-unknown的Rust目标。请注意,这个库目前只支持wasm-bindgenweb目标,不支持如no-modules之类的其他目标。

特性

  • 熟悉的API:如果您熟悉tokio,您会对tokio_with_wasm感到非常熟悉。它提供了类似的功能,并遵循相同的模式来启动和管理异步任务。

  • Web Worker集成tokio_with_wasm通过底层使用Web API来适应JavaScript环境。这意味着您可以为Web应用编写并发且高效的Rust代码。

  • 启动异步和阻塞任务:您可以启动异步和阻塞任务。异步任务允许您执行非阻塞操作,而阻塞任务适用于计算密集型或同步任务。

虽然将来可以添加各种I/O功能,但目前尚未包含。

使用方法

将此库添加到您的 Cargo.toml 文件中,与 tokio 并列。

[dependencies]
tokio = { version = "0.0.0", features = ["rt"] }
tokio_with_wasm = { version = "0.0.0", features = ["rt"] }

以下是一个使用 tokio_with_wasm 的简单示例。

use tokio_with_wasm::alias as tokio;

#[cfg_attr(target_family = "wasm", wasm_bindgen(start))]
#[cfg_attr(not(target_family = "wasm"), tokio::main(flavor = "current_thread"))]
async fn main() {
    let async_join_handle = tokio::spawn(async {
        // Your asynchronous code here.
        // This will run concurrently
        // in the same web worker(thread).
    });
    let blocking_join_handle = tokio::task::spawn_blocking(|| {
        // Your blocking code here.
        // This will run parallelly
        // in the external pool of web workers.
    });
    let async_result = async_join_handle.await;
    let blocking_result = blocking_join_handle.await;
    for i in 1..1000 {
        // Some repeating task here
        // that shouldn't block the JavaScript runtime.
        tokio::task::yield_now().await;
    }
}

use tokio_with_wasm::alias as tokio; 语句在功能上等同于下面的代码。这个导入提供了便利,并且可以缩短代码。

#[cfg(all(
    target_arch = "wasm32",
    target_vendor = "unknown",
    target_os = "unknown"
))]
use tokio_with_wasm as tokio;

#[cfg(not(all(
    target_arch = "wasm32",
    target_vendor = "unknown",
    target_os = "unknown"
)))]
use tokio;

文档

API 文档可以在 docs.rs 上找到。

注意

请记住,您绝对不应该编写会引发恐慌的代码。

对于 wasm32-unknown-unknown,目前 没有方法 来捕获和回滚像在本地平台那样的恐慌。恐慌最终会导致泄露 JavaScript Promise

尽可能使用 Result 枚举。

部署 Web 应用

在构建您的 WebAssembly 模块并准备部署后,请确保您的 Web 服务器已配置为在响应中包含与跨源相关的 HTTP 标头。将 Cross-Origin-Opener-Policy 设置为 same-origin,并将 Cross-Origin-Embedder-Policy 设置为 require-corp。这些标头允许使用您的网站的客户端访问 SharedArrayBuffer Web API,这类似于网络上的共享内存。此外,不要忘记在服务器配置中指定 application/wasm MIME 类型,以确保 .wasm 文件的最佳性能。

为什么需要这样做

由于网络沙盒环境的存在,网络有诸多限制,这阻止了线程、时间、文件 I/O、网络 I/O 等许多原生功能的的使用。因此,由于这些限制,Rust 的 std 中缺少某些功能。这就是为什么 tokio 在 Web 浏览器上并不真正有效的原因。

为了解决这个问题,这个包提供了与原始原生模块同名 的 tokio 模块,为这些限制提供了解决方案。

未来愿景

由于 Rust 的许多 Web 生态系统目前基于 wasm32-unknown-unknown,我们不得不创建 tokio 的别名包,以便直接在 Web 上使用其功能。

希望,当 wasm32-wasi 成为网络的主流 Rust 目标时,jco 可能会成为 wasm-bindgen 的替代品,因为它可以通过浏览器模拟(polyfills)提供完整的 std 功能。然而,这需要时间,因为 wasi-threads 建议还有很长的路要走。

在此之前,我们有 tokio_with_wasm

贡献指南

我们始终欢迎贡献!如果您有任何建议、错误报告或想要为 tokio_with_wasm 的开发做出贡献,请打开一个问题或提交一个拉取请求。

存在一些情况,您不能直接在网络上使用原生Rust代码。这是因为wasm32-unknown-unknown Rust目标,它是通过wasm-bindgen使用的,并没有完整的std模块。请参考以下链接了解如何使用wasm-bindgen与JavaScript交互。

Rust代码可以在Web Worker中被调用。因此,我们无法像在JavaScript的主线程中工作那样访问全局的window JavaScript对象。请参考以下链接检查在Web Worker中可用的Web API。您可能会对现代JavaScript的各种功能感到惊讶。

请注意,这个库使用了一种相当简单和原始的方法来模拟原生tokio功能。这是因为这个库被视为在wasm32-wasi之前的临时解决方案。只要能让事物在网络上正常工作,任何类型的PR都是可能的。

依赖项

~9–13MB
~223K SLoC