You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Promise链式调用中后续then未触发的问题求助(Docx转PDF场景)

问题排查与修复:Promise链第二个then未执行

问题背景

我正在开发一个微服务,可接收docx文件或HTML字符串,将输入转换为单个PDF文件并返回其链接。当前代码中,Promise.all完成文件上传后,第一个then调用convertFiles可正常触发,但第二个then未执行,导致Insomnia返回空响应,甚至console.log内容都没打印。

错误原因分析

  1. 正则匹配语法错误:concatFiles函数中使用了不存在的.matches()方法,正则也未转义.且未锚定结尾,会导致匹配逻辑失效。
  2. 未处理目录读取错误:fs.readdir的回调中未处理错误,一旦读取目录失败,Promise会一直处于pending状态,阻塞后续流程。
  3. 函数命名不匹配:代码中调用的是concatStoreFiles,但文件导出的是concatFiles,导致引用错误直接中断Promise链。
  4. 错误处理不完善: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:15:33