Node.js中Async/Await未等待问题:批量PDF串行处理失效求助
问题:Node.js中Async/Await遍历PDF列表无法逐个顺序执行
我在Node.js里用Async/Await时碰到问题,现在用wait函数替代实际的Tesseract.js OCR功能,两者表现一致。需求是逐个处理PDF文件名列表,等当前文件OCR完成后再处理下一个。试过递归、forEach、map、reduce都没解决,运行后所有日志立刻输出,之后才进入等待阶段,期望await能阻塞执行直到任务完成。
测试代码
const fs = require('fs'); const PdfList = fs.readdirSync("./Pdfs"); async function testReduce(array = []) { array = [""].concat(array); await array.reduce(async (a, pdf, pdfIndex) => { pdfIndex = pdfIndex - 1; //testing Stuff console.log("current PDF: " + pdf); console.log("current Index: " + pdfIndex); await wait(30000); }); console.log("testReduce"); } async function run() { await testReduce(PdfList); console.log("testBoth"); } run(); async function wait(ms) { return new Promise((resolve) => { console.log(ms); setTimeout(resolve, ms); }); }
运行输出(立刻全部打印)
current PDF: PROBATE - 180000529.pdf current Index: 0 30000 current PDF: PROBATE - 180000529pdf current Index: 1 30000 current PDF: PROBATE - 190000452.pdf current Index: 2 30000 current PDF: PROBATE - 190000452pdf current Index: 3 30000 current PDF: PROBATE - 200000501.pdf current Index: 4 30000 current PDF: PROBATE - 200000501pdf current Index: 5 30000 testReduce testBoth
问题原因
你的reduce用法错误:reduce的回调是异步函数,每次迭代都会立刻执行,不会等待前一个异步任务完成。因为reduce本身不会处理异步回调的返回值,你没有在回调里等待前一个Promise完成,导致所有wait几乎同时触发。
正确实现方式
方案1:用for...of循环(最直观)
直接用for...of遍历数组,天然支持顺序执行异步任务:
const fs = require('fs'); const PdfList = fs.readdirSync("./Pdfs"); async function processPdfs(array = []) { for (const [index, pdf] of array.entries()) { console.log("current PDF: " + pdf); console.log("current Index: " + index); await wait(30000); // 等待当前任务完成再进入下一次循环 } console.log("所有PDF处理完成"); } async function run() { await processPdfs(PdfList); console.log("testBoth"); } run(); async function wait(ms) { console.log(ms); return new Promise((resolve) => setTimeout(resolve, ms)); }
方案2:修复reduce的用法
如果一定要用reduce,需要在回调里等待前一个异步迭代的结果:
const fs = require('fs'); const PdfList = fs.readdirSync("./Pdfs"); async function testReduce(array = []) { await array.reduce(async (prevPromise, pdf, index) => { // 先等待前一个异步任务完成 await prevPromise; console.log("current PDF: " + pdf); console.log("current Index: " + index); await wait(30000); }, Promise.resolve()); // 初始值为已resolve的Promise console.log("testReduce"); } async function run() { await testReduce(PdfList); console.log("testBoth"); } run(); async function wait(ms) { console.log(ms); return new Promise((resolve) => setTimeout(resolve, ms)); }
内容的提问来源于stack exchange,提问作者Christian Langer
相关产品推荐
相关产品推荐

