You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin14整合Spring Boot时JS引入失败及CompletableFuture不触发问题求助

Vaadin 14 + Spring Boot 自定义JS导入及调用问题解答

1. JavaScript资源正确导入方式

Vaadin 14按照JS的类型分为两种标准导入方案,对应不同的存放路径和API:

  • 导入ES模块:使用@JsModule注解,JS文件需放在项目根目录的frontend/文件夹下,注解路径开头加./标识相对frontend根目录的路径,示例:@JsModule("./src/teams.js")。注意ES模块默认是隔离作用域,要暴露全局方法需要显式挂载到window对象上,不要直接覆盖整个window对象。
  • 导入普通全局JS文件:使用@JavaScript注解或者page.addJavaScript()方法,JS文件统一放在src/main/resources/META-INF/resources/目录下,比如存放在src/main/resources/META-INF/resources/js/teams.js,导入时写绝对路径@JavaScript("/js/teams.js")即可。不要在路径开头加.,.开头是相对当前页面路由的路径,路由变化后会出现资源找不到的问题。

2. 之前配置无效的原因

最开始的配置存在两个核心错误:

  • 全局对象覆盖问题:你的JS代码里直接写window = {initTeams:...},直接替换了整个浏览器全局window对象,Vaadin客户端运行时依赖的所有全局变量都会被清空,所以执行到window.initTeams()时直接抛出未定义错误,后续的console.log('xx')自然不会执行。正确的JS写法是window.initTeams = function () { console.log('initTeams...'); },仅给window添加属性而不是覆盖整个对象。
  • 路径规则匹配错误:使用@JsModule时路径没有加./相对前缀,Vaadin会默认到node_modules目录下查找对应文件,自然找不到你的自定义JS;使用frontend://前缀是Vaadin 13及更早版本的语法,14+版本已经废弃,会被识别为独立主机地址,因此报CORS跨域错误。

3. 调用join()导致浏览器冻结的原因

page.executeJs()返回的CompletableFuture是服务端异步对象,需要等待浏览器端JS执行完成后回传结果,才会触发future完成。你在视图构造函数中直接调用join()/get()会阻塞当前服务端请求线程,导致整个视图渲染请求无法完成,浏览器端一直收不到服务端响应,就会出现加载冻结的情况。这个API的设计是异步回调模式,绝对不能在请求处理线程中同步阻塞等待结果。

4. CompletableFuture回调始终不触发的原因

你在视图构造函数中执行page.executeJs()时,当前视图还没有完成客户端挂载,JS执行指令会被暂存到UI的待发送队列中,没有实际发送到浏览器端。如果后续视图渲染出现报错、UI实例被销毁,或者服务端没有开启推送/心跳机制,暂存的JS指令永远不会被发送,因此future永远不会完成,isSentToBrowser()方法始终返回false。
解决方法是把initTeams()的调用从构造函数移到beforeEnter生命周期方法中,这个阶段视图已经完成挂载,UI处于可交互状态,JS指令会被正常发送到浏览器执行。

内容的提问来源于stack exchange,提问作者Viktor Korai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 12:39:01