Promise链式调用中后续then未触发的问题求助(Docx转PDF场景)
问题排查与修复:Promise链第二个then未执行
问题背景
我正在开发一个微服务,可接收docx文件或HTML字符串,将输入转换为单个PDF文件并返回其链接。当前代码中,Promise.all完成文件上传后,第一个then调用convertFiles可正常触发,但第二个then未执行,导致Insomnia返回空响应,甚至console.log内容都没打印。
错误原因分析
- 正则匹配语法错误:
concatFiles函数中使用了不存在的.matches()方法,正则也未转义.且未锚定结尾,会导致匹配逻辑失效。 - 未处理目录读取错误:
fs.readdir的回调中未处理错误,一旦读取目录失败,Promise会一直处于pending状态,阻塞后续流程。 - 函数命名不匹配:代码中调用的是
concatStoreFiles,但文件导出的是concatFiles,导致引用错误直接中断Promise链。 - 错误处理不完善:convertFiles中exec执行出错时仅打印警告却仍resolve,且写入文件流未处理错误,可能导致隐式问题。
修复后的完整代码
主服务代码
// 'files' 是上传的docx文件数组。 const uploaded = files.map((file) => { return new Promise((resolve, reject) => { pump( file.toBuffer(), fs.createWriteStream(join(__dirname, 'files', file.filename)) .on('finish', resolve) .on('error', reject) // 新增:处理写入流错误 ) }) }) Promise.all(uploaded) .then(() => convertFiles()) // 简化async/await,直接返回Promise .then(async () => { // 统一函数命名,与导出保持一致 const test = await concatFiles(join(__dirname, 'files')) console.log({test}) res.send(test) }) .catch(err => { // 全局错误捕获,避免请求挂起 console.error('流程出错:', err) res.status(500).send('处理失败:' + err.message) }) const convertFiles = () => { return new Promise((resolve, reject) => { const cmd = `soffice --headless --convert-to pdf --outdir ${join(__dirname, 'files')} ${join(__dirname, 'files', '*.*')}` exec(cmd, (error, stdout, stderror) => { if (error) { console.warn(error) reject(error) // 出错时reject,让错误能被捕获 return } resolve(stdout ?? stderror) }) }) }
concatStoreFile.js(修正后)
module.exports = async function concatFiles (dirPath, outPath) { return new Promise ((resolve, reject) => { const existingFiles = [] fs.readdir(dirPath, (e, files) => { // 处理目录读取错误 if (e) { console.error('读取目录失败:', e) reject(e) return } files.forEach((file) => { // 修正正则:转义点号、锚定结尾,使用正确的test方法 if (/[\d\w_-]+\.pdf$/.test(file)) { existingFiles.push(file) } }); resolve(existingFiles) }) }) }
关键修复点说明
- 正则匹配修正:将
.matches()改为正确的.test()方法,正则中\.pdf$确保只匹配以.pdf结尾的文件,避免误匹配。 - 完善错误处理:
- 写入文件流添加
error事件监听,出错时reject Promise; fs.readdir处理错误,避免Promise长期pending;- convertFiles中exec执行失败时reject,让错误流入catch分支;
- 整个Promise链添加catch分支,捕获所有异常并返回错误响应,防止请求无响应。
- 写入文件流添加
- 统一函数命名:确保调用的函数名与导出的函数名一致,避免引用错误。
- 简化异步写法:第一个then中无需额外async包裹,直接返回convertFiles的Promise即可。
内容的提问来源于stack exchange,提问作者Jaeger
相关产品推荐
相关产品推荐

