如何从wasm_bindgen_futures::spawn_local中获取返回值?
在WASM中实现异步获取返回值(替代阻塞操作)
WebAssembly在Web环境下不支持阻塞操作,这是因为浏览器的JS线程是单线程的,阻塞会导致页面失去响应。解决这个问题的核心思路是:把异步逻辑全程用异步方式处理,不要试图同步获取异步操作的结果。
针对你用wasm-pack编译Rust到Web的场景,修改方案如下:
1. 把函数改为异步函数
直接将fetch_definitions定义为async fn,让它返回一个Result<WordDefs, Error>的Future,调用方可以通过await获取结果:
// 先确保自定义Error类型兼容gloo_net的错误 #[derive(Debug)] enum Error { CouldNotLookUpWord, HttpError(gloo_net::Error), } // 实现错误类型转换,方便用?操作符简化错误处理 impl From<gloo_net::Error> for Error { fn from(err: gloo_net::Error) -> Self { Error::HttpError(err) } } async fn fetch_definitions(def_dir: &str, spelling: &str) -> Result<WordDefs, Error> { let path = format!("{def_dir}/{spelling}_definitions.json"); // 直接在异步函数内执行网络请求,用?处理错误 let response = gloo_net::http::Request::get(&path) .send() .await? .json() .await?; Ok(response) }
2. 在异步上下文中调用函数
Web环境下的Future需要执行器驱动,你需要在合适的异步上下文里调用fetch_definitions:
在Rust代码中调用
用wasm_bindgen_futures::spawn_local启动异步任务,比如在初始化函数里:
use wasm_bindgen::prelude::*; use web_sys::console; #[wasm_bindgen(start)] async fn init() { match fetch_definitions("/defs", "hello").await { Ok(word_defs) => { // 处理获取到的定义数据 console::log_1(&format!("获取到定义: {:?}", word_defs).into()); } Err(e) => { console::error_1(&format!("获取失败: {:?}", e).into()); } } }
在JavaScript代码中调用
wasm-pack会把Rust的async fn转换成JS的Promise,你可以直接用await调用:
import { fetch_definitions } from './pkg/your_crate_name.js'; async function loadWordDefinitions() { try { const wordDefs = await fetch_definitions("/defs", "hello"); // 处理返回的定义数据 console.log("定义数据:", wordDefs); } catch (error) { console.error("加载定义失败:", error); } } loadWordDefinitions();
为什么之前的思路行不通?
你之前尝试用spawn_local启动Future后阻塞获取结果,但spawn_local仅负责把Future提交到浏览器微任务队列执行,本身不返回结果——而且Web环境下根本不存在支持阻塞的执行器(会导致页面卡死)。正确的做法是让整个调用链路保持异步,通过await获取异步操作的结果。
内容的提问来源于stack exchange,提问作者Diomedes
相关产品推荐
相关产品推荐

