Rust WASM中web_sys::fetch_with_request阻塞问题求助
排查与解决思路
核心问题:block_on阻塞浏览器主线程
浏览器是单线程事件循环模型,block_on会阻塞当前线程等待异步任务完成,这会直接卡死整个事件循环——包括Fetch请求的发起、网络响应的回调处理等所有异步操作都无法执行,导致代码永远卡在await fetch这一步,请求甚至根本没机会发送出去。
WASM在浏览器环境中运行在主线程,绝对不能用阻塞式的block_on来等待异步任务,必须遵循浏览器的异步模型。
解决步骤
1. 改用异步调用模式
移除block_on,将调用逻辑改为异步函数,通过wasm_bindgen_futures::spawn_local启动异步任务,或者暴露异步函数给JS端用async/await调用:
方式一:在WASM内部启动异步任务
use wasm_bindgen_futures::spawn_local; #[wasm_bindgen] pub fn load_shader(shader_name: &str) { spawn_local(async move { match fetch_as_vec_u8(&format!("http://localhost:8080/shaders/{}.vert.glsl", shader_name)).await { Ok(bytes) => { web_sys::console::log_1(&format!("Loaded shader, {} bytes", bytes.len()).into()); // 后续处理shader字节数据 } Err(e) => { web_sys::console::error_1(&e); } } }); }
方式二:暴露异步函数给JS调用
#[wasm_bindgen] pub async fn load_shader(shader_name: &str) -> Result<Vec<u8>, JsValue> { fetch_as_vec_u8(&format!("http://localhost:8080/shaders/{}.vert.glsl", shader_name)).await }
然后在JS中调用:
import { load_shader } from './your_wasm_module'; async function init() { try { const shaderBytes = await load_shader("your_shader_name"); // 处理shader数据 } catch (err) { console.error("加载shader失败:", err); } } init();
2. 补充调试日志,定位潜在问题
在关键步骤加入控制台日志,确认代码执行流程:
#[wasm_bindgen] pub async fn fetch_as_vec_u8(resource_name: &str) -> Result<Vec<u8>, JsValue> { web_sys::console::log_1(&format!("Fetching: {}", resource_name).into()); let opts = RequestInit::new() .method("GET") .mode(RequestMode::Cors); let request = Request::new_with_str_and_init(resource_name, &opts)?; request.headers().set("Accept", "application/octet-stream")?; web_sys::console::log_1(&"Created request, starting fetch...".into()); let window = web_sys::window().ok_or("No window found")?; let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?; web_sys::console::log_1(&"Fetch response received".into()); // 后续转换逻辑... }
3. 检查CORS与请求配置
- 如果当前页面Origin(如
localhost:3000)和资源服务器(localhost:8080)不同,需确保服务器返回正确的CORS响应头(如Access-Control-Allow-Origin: *或指定Origin)。 - 同Origin请求可将
RequestMode::Cors改为RequestMode::SameOrigin,避免不必要的CORS检查。
4. 确认web_sys特性开启
检查Cargo.toml中web-sys的features是否包含所需API:
[dependencies.web-sys] version = "0.3" features = [ "Window", "Request", "RequestInit", "RequestMode", "Response", "Headers", "Fetch", "ArrayBuffer", "console", ]
内容的提问来源于stack exchange,提问作者Vasili Korol
相关产品推荐
相关产品推荐

