AJAX 长耗时任务进度监听:解决“Pending”阻塞问题

AJAX 长耗时任务进度监听:解决“Pending”阻塞问题

本文旨在解决使用 ajax 监听服务器端长耗时任务进度时遇到的“请求挂起”(pending)问题。通过分析传统并发请求的局限性,文章提出并详细阐述了“链式 ajax 请求”的解决方案。这种方法将长任务分解为多个小步骤,客户端通过连续发送 ajax 请求来逐步执行并获取实时进度,从而避免了服务器端阻塞,实现了平滑的用户体验。

在Web开发中,我们经常会遇到需要执行耗时较长的服务器端操作(如数据导入、复杂计算等)的场景。为了提升用户体验,通常会考虑在客户端显示任务进度。然而,直接使用AJAX并发请求来监听进度时,常常会遇到一个棘手的问题:进度查询请求(如checkprogress.php)在网络面板中显示为“Pending”,直到主任务(如script.php)完成后才突然更新到100%。本文将深入探讨这一现象的原因,并提供一种有效的解决方案。

理解“Pending”阻塞现象

当客户端尝试通过两个独立的XMLHttpRequest对象同时向服务器发送请求时,如果其中一个请求(例如,执行长任务的script.php)长时间占用服务器资源或PHP会话锁,那么后续的请求(例如,查询进度的checkprogress.php)可能会被服务器挂起,直到第一个请求完成并释放资源。

原始代码分析:

在提供的代码示例中,index.php尝试通过两个独立的AJAX请求来管理进度:

xhr 对象: 发送请求到 script.php,该脚本模拟一个耗时10秒的循环,并每秒将当前进度写入 progress.txt 文件。xhr2 对象: 通过 setInterval 定时器,每100毫秒发送请求到 checkprogress.php,该脚本读取 progress.txt 的内容并返回给客户端更新进度条。

问题在于,当 script.php 正在执行时,它可能会锁定PHP会话或占用服务器的单个进程/线程资源。这意味着 checkprogress.php 的请求无法立即得到处理,而是在服务器端排队等待,直到 script.php 完成。因此,客户端看到的现象就是进度条一直停留在0%,然后瞬间跳到100%。

解决方案:链式 AJAX 请求

要解决这种并发请求阻塞的问题,核心思想是将一个长耗时任务分解成一系列小的、独立的子任务。客户端通过发送一个AJAX请求来执行一个子任务,等待其响应,然后根据响应数据决定是否继续发送下一个AJAX请求来执行下一个子任务。这种模式称为“链式 AJAX 请求”或“分步式处理”。

工作原理:

任务分解: 将长耗时任务拆分为多个原子性的步骤。状态管理: 服务器端需要一个机制来保存任务的当前状态(例如,已完成的步骤、总步骤数、中间结果等)。这可以通过文件、数据库、缓存或PHP会话来实现。客户端驱动: 客户端发起第一个请求,服务器执行第一个步骤并返回当前进度和下一个步骤所需的信息。客户端接收到响应后,更新UI,并根据需要再次发起请求执行下一个步骤,直到所有步骤完成。

这种方式确保了在任何给定时间,服务器端只有一个短平快的PHP脚本在处理请求,避免了长时间占用资源和会话锁,从而允许客户端实时获取进度更新。

实现链式 AJAX 进度的步骤

我们将改造原始的 script.php 和 index.php 来实现链式 AJAX。

1. 服务器端改造 (process_step.php)

不再让一个PHP脚本执行所有耗时操作,而是让它只执行一步,并返回当前状态。

process_step.php (示例代码)

 $progress,    'currentStep' => $currentStep,    'totalSteps' => $totalSteps,    'status' => ($currentStep > $totalSteps) ? 'done' : 'continue']);// 确保会话写入并解锁,以便其他请求可以访问session_write_close();?>

说明:

process_step.php 接收 step 参数,表示当前要执行的步骤。每次执行一个 sleep(1) 模拟一个耗时操作。计算当前进度并返回 JSON 格式的响应,包含 progress、currentStep、totalSteps 和 status。session_write_close() 非常重要,它会立即保存会话数据并释放会话锁,允许其他PHP脚本(即使是来自同一客户端的请求)立即执行,避免阻塞。

2. 客户端改造 (index.php)

客户端将负责发起第一个请求,并根据服务器的响应递归地发起后续请求。

index.php (客户端脚本部分示例)

    #container{        width: 300px;        height: 20px;        border: solid thin #aaa;    }    #progress{        background-color: lightblue;        height: 100%;        width: 0%; /* 初始宽度为0 */        color: grey;        text-align: center;        line-height: 20px; /* 使文字垂直居中 */    }
0%
var prog = document.getElementById('progress'); var startButton = document.getElementById('start'); var currentStep = 0; // 初始化步骤计数 startButton.onclick = function() { startButton.disabled = true; // 禁用按钮防止重复点击 currentStep = 0; // 重置步骤计数 prog.style.width = '0%'; prog.innerHTML = '0%'; // 启动第一个步骤 executeNextStep(currentStep); }; function executeNextStep(step) { var xhr = new XMLHttpRequest(); xhr.open("POST", "process_step.php", true); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onload = function() { if (xhr.status === 200) { try { var response = JSON.parse(xhr.responseText); prog.style.width = response.progress + "%"; prog.innerHTML = Math.round(response.progress) + "%"; // 显示整数百分比 if (response.status === 'continue') { // 如果任务未完成,继续执行下一个步骤 executeNextStep(response.currentStep); } else if (response.status === 'done') { // 任务完成 alert("Process completed!"); startButton.disabled = false; // 启用按钮 } } catch (e) { console.error("Error parsing JSON response:", e); alert("An error occurred during processing."); startButton.disabled = false; } } else { alert("Server error: " + xhr.status); startButton.disabled = false; } }; xhr.onerror = function() { alert("Network error occurred."); startButton.disabled = false; }; // 发送当前步骤参数 xhr.send("step=" + step); }

说明:

startButton 点击后调用 executeNextStep(0) 启动任务。executeNextStep 函数递归调用自身,每次发送 currentStep 参数给服务器。接收到服务器响应后,解析JSON,更新进度条,并根据 response.status 决定是继续调用 executeNextStep 还是标记任务完成。错误处理和按钮禁用/启用逻辑增加了用户体验。

注意事项与最佳实践

状态持久化: 在更复杂的场景中,任务状态可能需要存储在数据库中,以便在用户刷新页面或中断后可以恢复任务。错误处理: 客户端和服务器端都需要健壮的错误处理机制,以应对网络中断、服务器错误或数据处理失败等情况。用户反馈: 除了进度条,还可以提供文本提示(如“正在处理第 X 步,共 Y 步”)、动画效果等,增强用户体验。超时设置: 为AJAX请求设置合理的超时时间,防止因服务器无响应而导致客户端长时间等待。安全性: 如果任务涉及敏感数据或操作,确保所有AJAX请求都经过适当的身份验证和授权。并发限制: 虽然链式AJAX解决了单个长请求的阻塞问题,但如果同时有大量用户执行类似的长任务,服务器仍然可能面临压力。考虑使用消息队列、后台任务系统(如Gearman, RabbitMQ)来异步处理真正的长任务。WebSockets/SSE: 对于需要真正实时、双向通信的场景,WebSockets或Server-Sent Events (SSE) 是更优的选择,它们允许服务器主动向客户端推送更新,无需客户端频繁轮询。然而,它们的实现复杂度相对较高。

总结

通过将长耗时任务分解为一系列小的、可独立执行的步骤,并采用链式AJAX请求的模式,我们可以有效解决AJAX进度监听中遇到的“Pending”阻塞问题。这种方法不仅提供了实时的进度反馈,提升了用户体验,也优化了服务器资源的利用。在设计需要进度报告的Web应用时,理解并应用这种分步处理的策略至关重要。

以上就是AJAX 长耗时任务进度监听:解决“Pending”阻塞问题的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1333787.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
PHP中HTML字符串的正确转义处理与显示实践
上一篇 2025年12月12日 19:44:30
在Laravel项目中合并PDF文件:使用libmergepdf库实现
下一篇 2025年12月12日 19:44:41

相关推荐

  • AO3中文版官网入口 AO3网页版使用方法保姆级教程

    AO3中文版官网入口为https://archiveofourown.org,进入后点击右上角“语言”选择“中文(简体)”或“中文(繁体)”即可切换界面。 AO3中文版官网入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来AO3网页版使用方法保姆级教程,感兴趣的网友一起随小编来瞧瞧吧! …

    2026年9月26日
    100
  • 使用正则表达式判断字符串中字符是否全部唯一

    使用正则表达式判断字符串中字符是否全部唯一使用正则表达式判断字符串中字符是否全部唯一使用正则表达式判断字符串中字符是否全部唯一使用正则表达式判断字符串中字符是否全部唯一

    本文介绍如何使用Java正则表达式来判断一个字符串中的所有字符是否都是唯一的。我们将探讨一种使用正则表达式检测字符串中是否存在重复字符的方法,并提供相应的Java代码示例。通过本文,你将学习如何利用正则表达式的强大功能来解决字符串处理中的常见问题。 在字符串处理中,经常需要判断一个字符串中的字符是否…

    2026年9月25日 • 用户投稿
    000
  • sublime怎么解决许可证密钥(license key)无效问题 _sublime许可证密钥无效修复方法

    sublime怎么解决许可证密钥(license key)无效问题 _sublime许可证密钥无效修复方法sublime怎么解决许可证密钥(license key)无效问题 _sublime许可证密钥无效修复方法sublime怎么解决许可证密钥(license key)无效问题 _sublime许可证密钥无效修复方法sublime怎么解决许可证密钥(license key)无效问题 _sublime许可证密钥无效修复方法

    使用官方购买的正版密钥并清除非法残留可解决Sublime Text许可证无效问题,确保正确输入用户名和多行密钥,删除Local目录下的License.sublime_license文件,检查hosts文件是否屏蔽验证域名,重启软件后即可恢复正常。 Sublime Text 出现许可证密钥无效的问题,…

    2026年9月25日 • 用户投稿
    200
  • 淘宝支付方式无法切换怎么办 支付设置修改与修复方法

    淘宝支付方式无法切换怎么办 支付设置修改与修复方法淘宝支付方式无法切换怎么办 支付设置修改与修复方法淘宝支付方式无法切换怎么办 支付设置修改与修复方法淘宝支付方式无法切换怎么办 支付设置修改与修复方法

    首先检查默认支付设置并更换支付渠道,确认各支付方式状态正常,清除淘宝缓存或重启应用,更新淘宝与支付宝至最新版本,切换网络环境或尝试网页端操作,若仍无法解决则联系客服处理。 淘宝支付方式无法切换,可能是由于账户设置、网络问题或系统缓存导致。别着急,大多数情况下通过简单的设置调整就能解决。以下是几种常见…

    2026年9月25日 • 用户投稿
    100
  • 获取物品名称并转换为字符串时出现乱码的解决方案

    获取物品名称并转换为字符串时出现乱码的解决方案获取物品名称并转换为字符串时出现乱码的解决方案获取物品名称并转换为字符串时出现乱码的解决方案获取物品名称并转换为字符串时出现乱码的解决方案

    本文旨在解决在 Minecraft Spigot 插件开发中,获取玩家放置的物品名称并尝试将其转换为字符串时出现乱码的问题。通过分析问题原因,并提供正确的代码示例,帮助开发者避免类似错误,从而更有效地获取玩家名称。 在 Spigot 插件开发中,当玩家放置方块时,我们可能需要获取该方块对应的玩家名称…

    2026年9月25日 • 用户投稿
    100
  • Bukkit插件开发:正确处理物品显示名称与玩家识别

    Bukkit插件开发:正确处理物品显示名称与玩家识别Bukkit插件开发:正确处理物品显示名称与玩家识别Bukkit插件开发:正确处理物品显示名称与玩家识别Bukkit插件开发:正确处理物品显示名称与玩家识别

    本文旨在解决Bukkit插件开发中,从BlockPlaceEvent获取物品显示名称并将其用于玩家识别时常见的“乱码”问题。我们将深入探讨Component对象与纯文本字符串的区别,并提供两种核心解决方案:直接获取放置方块的玩家名称,以及如何正确地将Component转换为纯文本字符串,以避免不必要…

    2026年9月25日 • 用户投稿
    300
  • 云上书阁app如何绑定手机号_云上书阁app提升账户安全性操作

    云上书阁app如何绑定手机号_云上书阁app提升账户安全性操作云上书阁app如何绑定手机号_云上书阁app提升账户安全性操作云上书阁app如何绑定手机号_云上书阁app提升账户安全性操作云上书阁app如何绑定手机号_云上书阁app提升账户安全性操作

    绑定手机号可提升云上书阁App账户安全性,支持通过“我的”页面或设置菜单操作:进入账号与安全选项,输入手机号并验证短信验证码即可完成绑定。 如果您希望为云上书阁App的账户增加一层保护,绑定手机号是一项关键的安全措施。完成绑定后,您将能更方便地找回密码、接收安全提醒,并提升账户的整体安全性。 本文运…

    2026年9月25日 • 用户投稿
    000
  • sublime怎么折叠所有代码_sublime代码折叠快捷方法

    sublime怎么折叠所有代码_sublime代码折叠快捷方法sublime怎么折叠所有代码_sublime代码折叠快捷方法sublime怎么折叠所有代码_sublime代码折叠快捷方法sublime怎么折叠所有代码_sublime代码折叠快捷方法

    Sublime Text 支持多种代码折叠快捷键,Windows/Linux 使用 Ctrl + Shift + [/] 折叠/展开代码块,Ctrl + K, Ctrl + 1 展开所有用 Ctrl + K, Ctrl + J,macOS 用户将 Ctrl 替换为 Command。 在 Sublim…

    2026年9月25日 • 用户投稿
    200
  • sublime怎么实现sass/scss的自动编译_sublime配置SASS自动编译方法

    sublime怎么实现sass/scss的自动编译_sublime配置SASS自动编译方法sublime怎么实现sass/scss的自动编译_sublime配置SASS自动编译方法sublime怎么实现sass/scss的自动编译_sublime配置SASS自动编译方法sublime怎么实现sass/scss的自动编译_sublime配置SASS自动编译方法

    安装LiveSassCompiler插件并配置路径后,保存SCSS文件可自动编译为CSS。1. 通过Package Control安装插件;2. 设置输入输出路径;3. 保存文件触发编译,提升开发效率。 Sublime Text 要实现 SASS/SCSS 的自动编译,可以通过安装插件并配置构建系统…

    2026年9月25日 • 用户投稿
    200
  • 解析音调调整指令:一个Java教程

    解析音调调整指令:一个Java教程解析音调调整指令:一个Java教程解析音调调整指令:一个Java教程解析音调调整指令:一个Java教程

    本文旨在提供一个清晰易懂的Java教程,用于解析包含音调调整指令的字符串。通过使用正则表达式,我们可以从复杂的输入字符串中提取乐器名称、调整方向和调整量。本教程将详细解释代码实现,并提供示例,帮助读者理解如何在Java中处理这类问题。 使用正则表达式解析音调调整指令 在音乐领域,音调的微调至关重要。…

    2026年9月25日 • 用户投稿
    100
  • 货拉拉司机版怎样设置自动抢单参数_货拉拉司机版自动抢单的配置优化方法

    货拉拉司机版怎样设置自动抢单参数_货拉拉司机版自动抢单的配置优化方法货拉拉司机版怎样设置自动抢单参数_货拉拉司机版自动抢单的配置优化方法货拉拉司机版怎样设置自动抢单参数_货拉拉司机版自动抢单的配置优化方法货拉拉司机版怎样设置自动抢单参数_货拉拉司机版自动抢单的配置优化方法

    开启自动抢单并设置合理接单范围、筛选目标订单类型、匹配出车时间段及启用顺路单优先功能,可显著提升货拉拉司机接单效率。 如果您希望在货拉拉司机版中提升接单效率,合理配置自动抢单参数是关键。系统默认设置可能无法满足高峰时段或特定区域的接单需求,因此需要根据实际运营情况调整相关选项。以下是优化自动抢单配置…

    2026年9月25日 • 用户投稿
    000
  • Java字符串高级解析:使用正则表达式处理复杂指令模式

    Java字符串高级解析:使用正则表达式处理复杂指令模式Java字符串高级解析:使用正则表达式处理复杂指令模式Java字符串高级解析:使用正则表达式处理复杂指令模式Java字符串高级解析:使用正则表达式处理复杂指令模式

    本教程演示如何使用Java的java.util.regex包,通过正则表达式高效解析包含多条调音指令的复杂字符串。我们将学习构建匹配特定模式的正则表达式,并利用Pattern和Matcher类从输入字符串中准确提取乐器名称、调音方向和数值,从而将原始指令转换为清晰可读的输出格式。 1. 问题背景与挑…

    2026年9月25日 • 用户投稿
    100
  • 3D漫画在线阅读漫画入口 3D漫画免费漫画正版漫画在线浏览

    3D漫画在线阅读漫画入口 3D漫画免费漫画正版漫画在线浏览3D漫画在线阅读漫画入口 3D漫画免费漫画正版漫画在线浏览3D漫画在线阅读漫画入口 3D漫画免费漫画正版漫画在线浏览3D漫画在线阅读漫画入口 3D漫画免费漫画正版漫画在线浏览

    3D漫画在线阅读入口是https://www.3dmanhua.com/,该平台资源丰富、更新及时,提供高清流畅的阅读体验和简洁易用的操作界面,并支持个性化推荐、书架管理及夜间模式等贴心功能。 3D漫画在线阅读入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来3D漫画在线阅读浏览地址,喜…

    2026年9月25日 • 用户投稿
    100
  • sublime如何同步多台电脑的配置和插件 _sublime多设备配置同步方法

    sublime如何同步多台电脑的配置和插件 _sublime多设备配置同步方法sublime如何同步多台电脑的配置和插件 _sublime多设备配置同步方法sublime如何同步多台电脑的配置和插件 _sublime多设备配置同步方法sublime如何同步多台电脑的配置和插件 _sublime多设备配置同步方法

    通过管理Sublime Text配置目录并结合云盘或Git实现多设备同步。将Packages目录移至云盘并创建符号链接,或用Git版本化关键配置文件,配合Package Control自动恢复插件,确保各设备设置一致。 Sublime Text 是许多开发者喜爱的轻量级编辑器,跨设备使用时保持配置和…

    2026年9月25日 • 用户投稿
    100
  • sublime如何卸载插件 _sublime插件卸载教程

    sublime如何卸载插件 _sublime插件卸载教程sublime如何卸载插件 _sublime插件卸载教程sublime如何卸载插件 _sublime插件卸载教程sublime如何卸载插件 _sublime插件卸载教程

    通过Package Control卸载:打开Sublime Text,调出命令面板,输入Remove Package,选择插件并删除;2. 手动删除:关闭软件后进入Packages目录,删除对应插件文件夹;3. 注意清理User目录下的残留配置文件,避免冗余。操作安全,不影响主程序。 在 Subli…

    2026年9月25日 • 用户投稿
    100
  • Java中整数类型溢出行为详解:二进制补码与循环特性

    Java中整数类型溢出行为详解:二进制补码与循环特性Java中整数类型溢出行为详解:二进制补码与循环特性Java中整数类型溢出行为详解:二进制补码与循环特性Java中整数类型溢出行为详解:二进制补码与循环特性

    Java中原始整数类型在处理超出其范围的数值时,会遵循一种基于二进制补码的循环溢出机制。这意味着当正数溢出时会“回卷”为负数,反之亦然,如同数字在一个有限的圆环上循环。理解这一特性对于准确预测类型转换和算术运算结果至关重要。 计算机中的数值表示:位、字节与二进制 在计算机底层,所有数据都以二进制形式…

    2026年9月25日 • 用户投稿
    100
  • Java数据类型溢出:原理、预测与避免

    Java数据类型溢出:原理、预测与避免Java数据类型溢出:原理、预测与避免Java数据类型溢出:原理、预测与避免Java数据类型溢出:原理、预测与避免

    本文旨在深入解析Java中数据类型溢出的现象,阐述其背后的二进制补码原理,并提供预测溢出结果的方法。通过理解数据在计算机中的存储方式,以及溢出时数值的循环特性,开发者可以更好地掌握Java中的数据类型,避免潜在的错误。 数据在计算机中的存储:二进制补码 计算机底层使用二进制(bits)来表示所有数据…

    2026年9月25日 • 用户投稿
    100
  • 苹果壁纸设计网页正版访问_苹果壁纸设计网页直达入口

    苹果壁纸设计网页正版访问_苹果壁纸设计网页直达入口苹果壁纸设计网页正版访问_苹果壁纸设计网页直达入口苹果壁纸设计网页正版访问_苹果壁纸设计网页直达入口苹果壁纸设计网页正版访问_苹果壁纸设计网页直达入口

    苹果壁纸设计网页正版访问入口是http://eyu.zaixian-fanyi.com/fan_wei_13269529,该平台提供海量高清壁纸、支持用户上传分享、内置编辑工具并定期更新主题内容,界面简洁流畅,支持一键收藏与多设备同步,同时整合设计模板、贴纸素材与艺术字体,提升创作灵活性。 苹果壁纸…

    2026年9月25日 • 用户投稿
    100
  • MBTI测试免费入口网址_ MBTI官网免费测试网站链接

    MBTI测试免费入口网址_ MBTI官网免费测试网站链接MBTI测试免费入口网址_ MBTI官网免费测试网站链接MBTI测试免费入口网址_ MBTI官网免费测试网站链接MBTI测试免费入口网址_ MBTI官网免费测试网站链接

    MBTI测试免费入口网址是https://www.16personalities.com/,该网站提供无需注册即可参与的近百道题人格测试,耗时约10至15分钟,支持中文界面并可导出PDF报告。 MBTI测试免费入口网址在哪里?这是不少朋友都在寻找的,接下来由PHP小编为大家带来MBTI官网免费测试网…

    2026年9月25日 • 用户投稿
    400
  • sublime怎么运行php文件 _sublime PHP文件运行方法

    sublime怎么运行php文件 _sublime PHP文件运行方法sublime怎么运行php文件 _sublime PHP文件运行方法sublime怎么运行php文件 _sublime PHP文件运行方法sublime怎么运行php文件 _sublime PHP文件运行方法

    首先确保PHP已安装并加入环境变量,然后在Sublime Text中创建PHP构建系统:通过Tools → Build System → New Build System…添加对应操作系统的JSON配置,保存为PHP.sublime-build至User目录;接着打开.php文件按Ctrl+ B或C…

    2026年9月25日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信