WebAssembly 加载游戏资源时卡在主线程怎么办?

凌熙 ☘︎ 阅读 100

我用 Rust 编译成 WebAssembly 做一个小游戏,但每次加载 WASM 模块都会把页面卡住好几秒,用户根本没法操作。我看别人说可以用 Web Worker,但试了之后发现和主线程通信又特别麻烦。

有没有更简单的方法让 WASM 异步加载?比如像 import() 那样?我现在是这样加载的:

const wasm = await import('./pkg/game.js');
await wasm.default();
我来解答 赞 14 收藏
二维码
手机扫码查看
2 条解答
Prog.鸿吉
我之前踩过这个坑,WASM 模块加载确实会阻塞主线程,特别是当模块较大或者设备性能较弱的时候。你提到的用 Web Worker 是个不错的选择,虽然会增加一些复杂性,但确实能解决这个问题。

不过,如果你不想用 Web Worker,可以试试动态导入(dynamic import)。这种方式可以让 WASM 模块异步加载,不会阻塞主线程。你可以将你的加载代码改成这样:

import('./pkg/game.js').then(wasm => {
wasm.default();
}).catch(err => {
console.error('Error importing WASM:', err);
});


这样做的好处是加载过程不会阻塞主线程,用户体验会好很多。记得处理一下可能的错误,比如网络问题导致的加载失败。希望这能帮到你,避免掉我踩过的坑。
点赞
2026-03-21 14:17
皇甫梓睿
wasm-bindgen 编译的 WASM 默认是同步的,启用 async feature 就行。

Cargo.toml 加上:

[dependencies]
wasm-bindgen = { version = "0.2", features = ["async"] }


JS 端改成直接调 init()

import init from './pkg/game.js';await init();  // 这货返回 Promise,异步加载不卡主线程
// 之后该干嘛干嘛


init() 会自动 fetch WASM 文件并在后台编译,比 Web Worker 省心多了。
点赞
2026-03-17 08:03