0

0

如何在大型 JavaScript 文件加载完成前显示加载 Spinner

心靈之曲

心靈之曲

发布时间:2026-03-09 13:24:11

|

464人浏览过

|

来源于php中文网

原创

如何在大型 JavaScript 文件加载完成前显示加载 Spinner

本文介绍在 Shiny 应用中实现「页面启动时立即显示 Spinner,待外部大型 JS 文件完全加载后再自动隐藏」的可靠方案,核心是结合 的 defer 与 onload 属性,配合 Shiny.setInputValue() 触发服务端清理逻辑。

本文介绍在 shiny 应用中实现「页面启动时立即显示 spinner,待外部大型 js 文件完全加载后再自动隐藏」的可靠方案,核心是结合 `<script>` 的 `defer` 与 `onload` 属性,配合 `shiny.setinputvalue()` 触发服务端清理逻辑。</script>

在 Shiny 中,shinybusy::busy_start_up() 默认采用“启动即显”策略,但其底层依赖 Shiny 的初始化完成时机——而 <script src="..."> 同步加载(尤其 >17 MB 的巨型 JS)会阻塞 DOM 解析和 Shiny 初始化流程,导致 Spinner 实际出现时间严重滞后,甚至被用户感知为“无响应”。</script>

根本解法在于解耦 JS 加载与 Shiny 初始化:利用 HTML 原生能力控制脚本加载生命周期,并主动通知 Shiny 状态变更。

情感家园企业站5.0 多语言多风格版
情感家园企业站5.0 多语言多风格版

一套面向小企业用户的企业网站程序!功能简单,操作简单。实现了小企业网站的很多实用的功能,如文章新闻模块、图片展示、产品列表以及小型的下载功能,还同时增加了邮件订阅等相应模块。公告,友情链接等这些通用功能本程序也同样都集成了!同时本程序引入了模块功能,只要在系统默认模板上创建模块,可以在任何一个语言环境(或任意风格)的适当位置进行使用!

下载

✅ 正确实现步骤

  1. 启用 defer 属性:确保 JS 文件异步下载、延迟执行(不阻塞 HTML 解析),且保证在 DOM 构建完成后按顺序执行;
  2. 绑定 onload 回调:当 JS 文件加载并执行完毕后,触发自定义函数;
  3. 安全通信 Shiny:通过 Shiny.setInputValue() 向服务端发送信号(如 "done": true),避免直接操作 remove_start_up() 导致竞态;
  4. 添加微小延迟(必要 Hack):因 onload 可能在 Shiny JS 框架就绪前触发,使用 setTimeout(..., 100) 确保 Shiny 全局对象已可用;
  5. 设置 mode = "manual":禁用 busy_start_up() 的自动超时逻辑,由 JS 主动控制关闭时机。

? 完整可运行示例

library(shiny)
library(shinybusy)
library(bslib)

ui <- page_sidebar(
  tags$head(
    # 定义 onload 回调函数(必须先声明,确保作用域)
    tags$script(HTML("
      function notifyJSLoaded() {
        setTimeout(() => {
          if (typeof Shiny !== 'undefined' && typeof Shiny.setInputValue === 'function') {
            Shiny.setInputValue('js_loaded', true);
          }
        }, 100);
      }
    ")),
    # 关键:defer + onload 组合
    tags$script(src = "HUGE_JAVASCRIPT_FILE.js", defer = NA, onload = "notifyJSLoaded()")
  ),

  # 手动模式:仅靠 JS 信号关闭,不依赖超时
  busy_start_up(
    loader = spin_epic("orbit", color = "#FFF"),
    text = "Loading large JavaScript library...",
    mode = "manual",
    color = "#FFF",
    background = "#112446"
  ),

  title = "Gröbner implicitization with GIAC",

  sidebar = sidebar(
    textInput("equations", "Equations:", value = "x = a*cost, y = b*sint"),
    textInput("relations", "Relations:", value = "cost^2 + sint^2 = 1"),
    textInput("symbols", "Symbols:", value = "cost, sint, a, b"),
    actionButton("go", "Run", class = "btn-primary")
  )
)

server <- function(input, output, session) {
  # 监听 JS 加载完成信号,立即移除启动 Spinner
  observeEvent(input$js_loaded, {
    remove_start_up()
  })
}

shinyApp(ui, server)

⚠️ 注意事项与最佳实践

  • 文件路径验证:确保 HUGE_JAVASCRIPT_FILE.js 存放于 www/ 目录下,Shiny 会自动托管该目录;
  • 避免 async:async 不保证执行顺序,若 JS 依赖其他库或全局变量,请坚持用 defer;
  • 错误防御:生产环境建议在 notifyJSLoaded 中增加 try/catch 和加载失败兜底(如 onerror 处理);
  • 性能监控:可在 larger.js 开头/结尾插入 console.time("JS load") / console.timeEnd("JS load") 辅助调试;
  • 替代方案权衡:若 JS 仅需部分功能,考虑模块化拆分 + 动态 import(),但需重写 JS 为 ES Module 格式。

通过该方案,Spinner 将在 HTML 解析开始后立即呈现,用户获得即时反馈;而关闭时机精准锚定在目标 JS 执行完毕之后,兼顾体验与可靠性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

91

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

106

2025.09.18

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

530

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

556

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

739

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

6118

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

492

2023.09.01

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

220

2023.09.04

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

59

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 5.9万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.3万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号