
ToolJet RunJS 查询调试指南主动抛出 ReferenceError 验证失败事件处理【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet本篇技术文章围绕 ToolJet 中「故意让 RunJS 查询失败」这一调试技巧展开通过一条throw new ReferenceError(...)语句人为制造查询失败再配合失败事件处理器onFailure 场景下的 Alert 动作验证错误提示链路。读完本文你将掌握如何在 ToolJet 查询面板中构造可控的错误、理解前端如何执行 JS 查询并捕获异常、以及查询面板是如何对错误类型ReferenceError / TypeError / SyntaxError进行分类展示的从而提升应用代码的健壮性与可调试性。场景说明为什么要让查询“故意失败”在构建内部工具与仪表板时开发者通常需要验证以下两类行为失败路径是否被正确处理当查询抛出异常时绑定的事件处理器例如弹出一个 Alert 提示用户能否被正确触发错误信息是否对用户友好查询面板、预览框中呈现的错误类型与消息是否符合预期。而“故意制造一次失败”是最小成本、可重复验证这两点的方式。本指南演示的方法核心只有一行 JavaScript 代码——利用ReferenceError构造器主动抛出一个引用错误throw new ReferenceError(This is a reference error.);ReferenceError是 JavaScript 内置的异常类型之一通常表示代码引用了未定义的变量。这里我们不是真的存在“未定义变量”的问题而是借用它的构造函数来主动生成一个带自定义消息的错误对象作为调试失败的“触发器”。操作步骤创建会抛错的 RunJS 查询以下步骤完整继承自官方文档 intentionally-fail-js-query.md并补充了每个步骤对应的界面位置。步骤 1新建一个 RunJS 查询打开 ToolJet 的 App Builder 界面在查询面板Query Panel中点击 Add按钮选择Run JavaScript内部标识为runjs数据源类型创建一个 RunJS 查询。步骤 2粘贴抛错代码将上面的代码粘贴到 RunJS 查询编辑器中throw new ReferenceError(This is a reference error.);这条语句会在查询执行的第一时间抛出异常查询必然进入失败状态。步骤 3为查询添加失败事件处理器在查询的事件配置中为其添加一个失败onFailure事件处理器处理器动作设置为显示 Alert。这样当查询失败时界面上会弹出提示框直观证明“失败事件确实被触发了”。步骤 4点击 Run 观察结果点击查询的Run按钮执行查询。此时你会看到查询状态变为失败查询面板的预览区域展示错误消息This is a reference error.失败事件处理器被触发Alert 弹窗出现。按官方文档的总结通过这种方式模拟 RunJS 查询中的错误可以有效辅助调试流程并提升整体代码的健壮性simulating errors in RunJS queries aids in the debugging process and improving the overall robustness of your code。原理深入ToolJet 前端是如何执行 RunJS 并捕获异常的上面的“故意失败”之所以能被稳定观察到是因为 ToolJet 前端对 JS 查询的执行与错误捕获有明确的实现。以下分析基于仓库源码。JS 代码在受控沙箱中执行RunJS 查询的前端执行逻辑位于 queryPanelSlice.js。从源码结构看ToolJet 通过new Function(...)动态构造一个AsyncFunction把查询代码作为函数体并向其注入一组预置参数const AsyncFunction new Function(return Object.getPrototypeOf(async function(){}).constructor)(); const fnParams [ moment, _, components, queries, globals, page, axios, variables, actions, constants, setTimeout, setInterval, clearTimeout, clearInterval, requestAnimationFrame, cancelAnimationFrame, // 若查询定义了参数还会注入 parameters模块应用还会注入 input ...Object.keys(libraryRegistry), code, ]; var evalFn new AsyncFunction(...fnParams);这意味着在 RunJS 查询内你可以直接使用moment、_Lodash、axios以及components、queries、globals、variables、constants、actions等 ToolJet 运行时对象。这也解释了为什么故意抛错时只需一行throw——它运行在与其他查询脚本完全相同的执行环境中因此失败行为与实际业务代码出错时完全一致。异常被捕获后转为结构化失败结果同文件的catch分支queryPanelSlice.js展示了抛出的ReferenceError如何变成查询面板上的失败状态} catch (err) { const stackLines err.stack.split(\n); const errorLocation stackLines[2]?.match(/anonymous:(\d):(\d)/) ?? stackLines[1]?.match(/anonymous:(\d):(\d)/); let lineNumber null; if (errorLocation) { lineNumber errorLocation[1] - 2; } console.log(JS execution failed: , err); error err.message || err.stack.split(\n)[0] || JS execution failed; result { status: failed, data: { message: error, description: error, lineNumber } }; }这里有三个关键点错误消息取自err.message因此new ReferenceError(This is a reference error.)中的自定义字符串会原样呈现在查询面板中方便确认“是这条语句触发的失败”会解析堆栈定位出错行号lineNumber被提取出来随失败结果返回用于在编辑器中高亮出错位置失败结果被结构化为{ status: failed, data: { message, description, lineNumber } }查询状态机据此把查询标记为失败进而触发绑定在查询上的失败事件处理器——这正是步骤 3 中 Alert 能被弹出的底层原因。此外源码在成功路径之后还有一层保护若查询结果存在循环依赖hasCircularDependency(result)也会被强制转换为status: failed并提示 Circular dependency detected。这提示我们在构造故意失败的查询时抛错是最干净的失败方式避免与循环依赖检测等其他失败路径混淆。错误在查询面板中的展示与分类查询失败后错误信息最终由预览组件呈现。PreviewBox.jsx 中可以看到 ToolJet 会对错误字符串做类型归类const jsErrorType isSecretError ? Error : _error?.includes(ReferenceError) ? ReferenceError : _error?.includes(TypeError) ? TypeError : _error?.includes(SyntaxError) ? SyntaxError : Invalid; setError({ message: ..., value: ..., type: isSecretError ? Error : jsErrorType, completeErrorMessage: completeErrMessage, });随后在 PreviewBox.jsx 中错误类型会以徽标badge形式展示预览框切换为错误横幅样式并可通过 AI 辅助修复入口FixWithAi尝试自动修复。从源码结构看这种分类意味着你可以换用不同的内置错误类型来观察展示差异throw new TypeError(This is a type error.); throw new SyntaxError(This is a syntax error.); throw new Error(This is a generic error.);ReferenceError/TypeError/SyntaxError会被单独归类并在徽标中体现其他错误如普通Error会归入其他分类分支展示。这对调试很有价值如果你的业务代码实际抛出的错误类型不同用对应的错误构造器复现同类失败可以验证面板与事件处理逻辑对各种异常形态的反应是否一致。RunJS 在 ToolJet 中的定位默认数据源之一RunJS 不是实验性功能而是 ToolJet 内建的默认数据源类型之一。服务端constants/index.ts 中runjs与restapi、runpy、tooljetdb、workflows一起被列为DefaultDataSourceKinds即新应用开箱即用的数据源类型前端Runjs.schema.json 定义了该数据源的元信息显示名为 Run JavaScript、kind为runjs并声明了对外暴露的变量{ source: { name: Run JavaScript, kind: runjs, exposedVariables: { isLoading: false, data: [], rawData: [] }, customTesting: true, disableTransformations: true } }两点值得注意exposedVariablesRunJS 查询向应用其他组件暴露isLoading、data、rawData三个变量。查询失败时data会承载失败信息即上文的message/description其他组件可以基于它做条件渲染disableTransformations: trueRunJS 禁用响应转换response transformations因为它返回的是 JS 代码的任意结果而非标准 HTTP 响应——所以故意抛错时不存在“转换层吞掉错误”的干扰失败路径直接可见。调试技巧与注意事项结合上述实现给出几条实操建议最小化错误查询调试失败事件时让查询只包含一行throw语句。这样堆栈解析得到的lineNumber稳定指向该行失败结果中err.message即你写入的自定义消息便于断言式验证例如在 E2E 测试中断言预览区出现特定错误文本。优先用自定义消息标识触发源new ReferenceError(This is a reference error.)这类带明确消息的构造比裸throw oops更容易在预览框和事件处理器回调中被识别失败结果的message字段直接取自err.message见 queryPanelSlice.js 的 catch 分支。验证事件链路时关注两个出口一是查询面板预览框的错误横幅由 PreviewBox.jsx 渲染二是绑定在查询上的失败事件处理器动作如 Alert。两者同时出现说明从异常抛出 → 状态机标记失败 → 事件分发 → 动作执行的完整链路工作正常。注意运行环境与版本前提本文的执行机制描述基于当前仓库的前端实现frontend/src下的queryPanelSlice.js与PreviewBox.jsx。不同版本 ToolJet 的查询面板交互按钮位置、事件配置面板命名可能有差异具体操作界面请以你所部署版本的实际界面为准机制层面AsyncFunction 执行、错误结构化、类型归类与当前源码一致。不要在生产查询里留调试语句故意抛错的代码只应存在于调试用途的临时查询中。完成失败事件验证后应删除该查询或移除throw语句避免污染应用的查询列表与 Git 同步记录。小结通过一条throw new ReferenceError(...)语句你可以在 ToolJet 中低成本地复现一次可控的 RunJS 查询失败并借此验证失败事件处理器、错误展示与错误归类逻辑。源码层面该机制依托 queryPanelSlice.js 中的 AsyncFunction 执行与异常捕获、PreviewBox.jsx 中的错误类型归类以及 Runjs.schema.json 定义的数据源契约完整覆盖了“抛出 → 捕获 → 呈现 → 触发事件”的调试闭环。【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考