如何在浏览器WASM应用中从JavaScript调用Ruby方法
在浏览器中从JavaScript调用WASM化Ruby方法的正确方式
核心逻辑
Ruby编译为WASM后,其方法默认处于Ruby自身的作用域,不会自动暴露给JavaScript。必须通过显式绑定或指定接口,才能让JS访问到Ruby方法。
具体实现方案
方案一:将Ruby方法挂载到JS全局对象
编写Ruby代码时,把需要调用的方法绑定到$global(对应JS的window对象):
# 定义业务方法 def calculate_total(price, quantity) price * quantity * 1.08 # 加8%税费 end # 暴露给JavaScript全局作用域 $global.calculate_total = method(:calculate_total)
将上述代码用ruby.wasm编译为WASM模块后,在HTML中加载并调用:
<script src="https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@0.5.0/dist/browser.script.iife.js"></script> <script> async function initRuby() { const { DefaultRubyVM } = window["ruby-wasm-wasi"]; const vm = await DefaultRubyVM(); // 加载编译好的WASM文件 await vm.instantiateStreaming(fetch('./app.wasm')); // 直接调用全局对象上的Ruby方法 const total = window.calculate_total(100, 2); console.log(`最终总价:${total}`); // 输出:最终总价:216 } initRuby(); </script>
方案二:通过RubyVM接口直接调用
如果不想污染全局作用域,可以通过vm.eval执行Ruby代码并获取返回值:
async function callRubyFunc() { const { DefaultRubyVM } = window["ruby-wasm-wasi"]; const vm = await DefaultRubyVM(); // 先在Ruby环境中定义方法 await vm.eval(` def format_date(date_str) Date.parse(date_str).strftime("%Y年%m月%d日") end `); // 调用方法并转换结果为JS可识别类型 const formattedDate = await vm.eval(`format_date("2024-05-20")`); console.log(formattedDate.toString()); // 输出:2024年05月20日 } callRubyFunc();
关键注意事项
- 作用域隔离:Ruby和JS的作用域完全独立,未显式导出的Ruby方法无法被JS直接访问。
- 参数类型兼容:基础类型(字符串、数字)可自动转换,复杂对象需手动做序列化/反序列化处理。
- 异步处理:WASM初始化和方法调用均为异步操作,需用
async/await处理流程。
内容的提问来源于stack exchange,提问作者zachaysan
相关产品推荐
相关产品推荐

