ExecJS 完整指南:3 个方法让 Ruby 跑 JavaScript
ExecJS 完整指南3 个方法让 Ruby 跑 JavaScript【免费下载链接】execjsRun JavaScript code from Ruby项目地址: https://gitcode.com/gh_mirrors/ex/execjs接了个活要在 Ruby 脚本里把一段 CoffeeScript 编译成标准 JS但你不想手写系统调用去管理子进程和临时文件。这就是 ExecJS 要解决的事——从 Ruby 中执行 JavaScript 代码结果直接以 Ruby 对象的形式返回。这篇文章作为一份精简的 ExecJS 使用指南带你走通 eval、compile、call 三个方法看完就能上手。安装 ExecJS 并自动检测 JS 运行时gem install execjsrequire execjs后它会按内置优先级自动探测系统里可用的 ExecJS 运行时Node.jsV8、JavaScriptCore、therubyracer 依次查找找到第一个就绑定。你可以用环境变量EXECJS_RUNTIME强制指定某个运行时想确认最终选中了谁跑一句puts ExecJS.runtime.name即可。检测逻辑都在lib/execjs/runtimes.rb里十几行代码值得一读。一张图看懂 eval、compile、call 的分工方法一句话定位适用场景调用开销ExecJS.eval一次性执行片段并拿回返回值单次计算、快速验证每次都新建执行上下文最重ExecJS.compile预编译脚本得到一个可复用上下文加载大库后反复使用编译一次后续调用很轻context.call直接调上下文里的函数并传参高频调用、参数是数组/对象最轻参数按 JSON 序列化传入先记住这张表下面按「最轻 → 最重」逐个看。一行 eval 执行 JSExecJS.eval接收一段 JS 字符串把执行结果转成 Ruby 对象返回require execjs ExecJS.eval(hello world.split( ).length) # 2用法和直觉一致但有两个坑要提前知道⚠️ 每次eval都创建一个全新的执行上下文这次定义的变量下次调用就不见了无法共享状态不要拿不受信任的输入来eval它和 Ruby 自己的eval是同一危险等级。对外部运行时Node.js 这类来说每次调用都要启动一次子进程所以eval只适合低频场景。用 compile 建立可复用的 JS 上下文需要反复执行同一段代码时用ExecJS.compile。它把脚本编译进一个上下文之后在这个上下文里 eval 或 call 都可以ctx ExecJS.compile(function shout(t) { return t.toUpperCase() !!; }) ctx.eval(shout(hello)) # HELLO!! 注意传给compile的字符串在上下文创建时就会立刻执行所以语法错误会在编译这一步就抛出来。这其实是好事——问题在真正干活之前就被暴露了排查成本最低。用 context.call 传参调用 JS 函数context.call直接调用上下文里已定义的函数Ruby 侧的值作为参数传进去ctx ExecJS.compile(function joinAll(items) { return items.join(-); }) ctx.call(joinAll, [a, b, c]) # a-b-c第一个参数是函数名也支持点号路径调嵌套函数比如ctx.call(obj.helper, 1)。⚠️ 如果函数名写错或函数不存在会抛ProgramError错误信息里能看到具体是哪个路径。回到开头的场景编译 CoffeeScript 的完整流程其实只有三行source File.read(vendor/coffee-script.js) ctx ExecJS.compile(source) ctx.call(CoffeeScript.compile, half (n) - n / 2, bare: true) # var half;\nhalf function(n) {\n return n / 2;\n};大库只compile一次后续多少次转换都走同一个上下文这是性能差异最大的地方。eval 还是 call怎么选你的场景选它只想算一个表达式拿结果ExecJS.eval加载大型 JS 库之后要多次使用一次ExecJS.compile之后 eval / call反复调用同一函数参数较复杂context.call两段 JS 之间要共享变量或状态定义放compile逻辑放context.eval判断规则一句话复用的次数越多越应该尽早 compile参数越多、调用越频繁越应该走 call。排错速查常见异常与处理所有 JS 调用建议都包一层 rescue异常自带 JS 侧的调用栈能直接定位出问题的行begin ExecJS.eval(boom()) rescue ExecJS::ProgramError e puts JS 运行错误: #{e.message} end异常含义怎么处理ExecJS::RuntimeUnavailable系统里找不到可用的 JS 运行时装一个 Node.js或用EXECJS_RUNTIME指定已有的ExecJS::ProgramErrorJS 运行时错误变量未定义、函数调用失败等rescue 捕获看异常里的 JS 栈定位ExecJS::RuntimeErrorJS 语法错误先修 JS 语法源码里 SyntaxError 就归在这类再提醒一点ExecJS 提供的是各运行时之间的「最小公共接口」require、setTimeout这些 Node 专属 API 不可用你的 JS 要按独立可执行来写。外部运行时比如 Node的具体执行实现可以看 lib/execjs/external_runtime.rb。下一步可以做的 3 件事跑puts ExecJS.runtime.name确认你机器上选中的 ExecJS 运行时是谁把一个正在用的ExecJS.eval改成 compile call对比输出是否一致给所有 JS 调用加上begin/rescue ExecJS::ProgramError打印异常信息先把错误兜住。【免费下载链接】execjsRun JavaScript code from Ruby项目地址: https://gitcode.com/gh_mirrors/ex/execjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考