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

同步函数表现为异步如何await?html-pdf执行顺序异常求解

问题原因

你遇到的执行顺序错乱是典型的回调式异步代码执行时序问题,和TypeScript类型提示没有关系:

  • html-pdf是比较老的Node包,它的toBuffer方法是标准的错误优先回调风格异步API,不会阻塞后续同步代码执行
  • 你调用toBuffer传入回调函数后,JS会把这个回调暂存到异步任务队列,立刻往下执行外层的日志打印、uploadFile调用,等所有同步代码跑完,才会回头执行回调里的blob、pdfSize赋值逻辑,这就是为什么你在外层拿到的永远是undefined
  • 直接await pdf.create()不生效是因为pdf.create()返回的是支持链式调用的实例对象,不是Promise,await非Promise值不会产生任何等待效果。
修复方案

把回调风格的toBuffer包装成Promise,配合async/await实现按预期顺序执行,修改后的代码如下:

resolve: async (parent, args, { req }) => {
  try {
    // ...其余原有前置逻辑
    const pdfId = uuidv4();
    
    // 包装回调为Promise,等待PDF生成完成再往下走
    const { blob, pdfSize } = await new Promise<{
      blob: Blob;
      pdfSize: number;
    }>((resolve, reject) => {
      pdf.create(args.data.htmlTemplate, {
        // ...原有PDF配置项
      }).toBuffer((err, buffer) => {
        if (err) {
          return reject(err);
        }

        const blobVal = Buffer.from(buffer).toString('base64') as unknown as Blob;
        const sizeVal = Buffer.byteLength(buffer);
        console.log('BLOB AND SIZE: ', blobVal, sizeVal);
        resolve({
          blob: blobVal,
          pdfSize: sizeVal
        });
      });
    });

    console.log('BLOB AND SIZE OUTSIDE: ', blob, pdfSize);
    await uploadFile(pdfId, blob as unknown as string, 'application/pdf');
    // ...其余原有后续逻辑
  } catch (error) {
    console.error(JSON.stringify(error, null, 2));
    if (error instanceof Error) {
      throw new Error(error.message);
    }
  }
},

修改后执行顺序会完全符合你的预期:先等PDF生成、blob和size赋值完成、打印回调内日志,再打印外层日志、执行上传逻辑。

补充:所有Node生态里参数为(err, 返回值) => void形式回调的方法,默认都是异步非阻塞的,不要尝试在外层声明变量等回调赋值,要么把后续逻辑写在回调内,要么包装成Promise配合await使用。

内容的提问来源于stack exchange,提问作者SlothOverlord

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:03:25