如何实现Ajax POST请求完成后再调用JS异步readFile函数
核心问题
你当前的代码存在3个直接导致时序错乱的问题:
prepare.js顶层的立即执行函数在脚本加载完成后就会自动运行,既不等待参数传入,还写死了读取gfhgf.png测试文件,和业务逻辑完全脱节$.post请求prepare.php时没有处理返回内容,PHP输出的<script>标签根本不会被插入页面执行,等于无效代码prepare.php里判断触发逻辑的条件是!empty($_POST["mail"]),但你POST请求只传了filename参数,这个判断永远不会成立
修复方案
按前后端职责拆分原则调整代码结构,把依赖加载、接口返回、逻辑触发的时序完全对齐。
1. 修改prepare.js:移除自动执行逻辑,封装显式调用入口
保留原有业务函数,删除加载即执行的顶层立即执行函数,把全量OCR流程封装成全局可调用的入口函数,只有收到调用指令、拿到正确文件路径时才执行,同时修复原代码中JSON.parse传入数组的语法bug:
async function readFile(fileName) { console.log({ fileName }); return await Tesseract.recognize(fileName, 'ara', { logger: m => console.log(m) }); } async function parseDataFromTextAndPropertyNames(text, propertyNames) { console.log({ text, propertyNames }); return propertyNames.reduce((table, key) => Object.assign(table, { [key]: RegExp(`${key}\\W+(\\w+)`).exec(text)?.[1] ?? '' }), {}); } async function writeParsedTextDataAsJSON(fileName, table) { console.log({ table }); JSON.stringify({ table }); return await new Promise(resolve => setTimeout(() => { console.log({ fileName, json: JSON.stringify({ table }) }); resolve({ success: true }); }, 1500) ); } // OCR流程全局入口,接收动态传入的目标文件路径 async function startOCRProcess(fileName) { try { const { data: { text } } = await readFile(fileName); const data = await parseDataFromTextAndPropertyNames(text, ['نقطة الخدمة', 'رقم العداد']); document.getElementById("dvjson").innerHTML = JSON.stringify(data, undefined, 4); const final = JSON.stringify(data); console.log(data); console.log(text); const ff = [JSON.parse(final)]; console.log(final) console.log(ff); constructTable('#table',ff); $("#table").excelexportjs({ containerid: "table", datatype: 'table', dataset: data, columns: getColumns(data) }); const result = await writeParsedTextDataAsJSON('myjsonfile.json', data); console.log({ result }); } catch (err) { console.error('OCR处理失败:', err); } }
改完后这个脚本加载时只会注册函数,不会自动执行任何业务逻辑。
2. 修改prepare.php:纯做后端接口,返回结构化JSON数据
这个文件是Ajax请求的后端接口,不需要加载任何前端JS,也不要输出<script>标签,只负责校验参数、返回结构化结果:
<?php $uploadedImage = $_POST['filename'] ?? ''; if (empty($uploadedImage)) { http_response_code(400); echo json_encode(['code' => 400, 'msg' => '缺少文件名参数']); exit; } // 此处可新增你需要的后端逻辑,比如校验文件是否存在、处理mail参数等 echo json_encode([ 'code' => 200, 'msg' => '参数接收成功', 'data' => ['filename' => $uploadedImage] ]); ?>
3. 修改upload.php:提前加载所有依赖,在Ajax成功回调里触发OCR
把所有前端依赖统一在上传页提前加载(全部用本地文件,不要依赖外部资源),修改Ajax请求逻辑,只有在收到接口成功返回的有效参数后,才调用OCR入口函数:
<!-- 提前加载所有本地前端依赖 --> <script src='scripts/jquery.min.js'></script> <script src='scripts/tesseract.min.js'></script> <script src='scripts/prepare.js'></script> <script> function prepareforconvert(filename){ $.post('prepare.php', {filename: filename}, function(response){ const res = JSON.parse(response); if (res.code === 200) { alert('文件上传完成,开始OCR识别'); // 拿到有效参数后才触发OCR全流程 startOCRProcess(res.data.filename); } else { alert('参数校验失败:' + res.msg); } }).fail(function(err){ alert('请求预处理接口失败'); console.error(err); }); } </script> <?php if (move_uploaded_file($_FILES["uploadedFile"]["tmp_name"], $target_file)) { $target_file = $target_dir . basename($_FILES["uploadedFile"]["name"]); echo "File ". basename( $_FILES["uploadedFile"]["name"]). " uploaded success."; echo $target_file; // 此处输出的脚本执行时,所有依赖已经加载完成,不存在时序问题 echo '<script>prepareforconvert("'.$target_file.'")</script>'; } ?>
逻辑说明
- 所有前端依赖提前在主页面加载完成,不存在Ajax动态插脚本导致的作用域丢失、加载时序不确定问题
- 前后端职责拆分清晰:后端只返回数据,前端只负责逻辑执行,不会出现PHP拼脚本导致的各种诡异bug
- OCR流程的触发时机完全可控:只有文件上传成功、POST请求返回200状态、拿到合法文件路径三个条件同时满足时,才会启动识别流程,彻底解决自动执行、参数丢失的问题
- 新增了错误捕获和请求失败提示,排查问题更方便
内容的提问来源于stack exchange,提问作者MrObscure
相关产品推荐
相关产品推荐

