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

使用GridFS保存音频数据时文件ID返回同步问题求助

问题修复方案

你的核心问题是saveAudioToGridFS函数没有正确处理异步逻辑,导致无法返回文件ID。下面是具体修复步骤和代码:

1. 将saveAudioToGridFS包装为Promise

流操作是异步的,必须通过Promise封装,才能让调用端获取异步结果:

function saveAudioToGridFS(audioBlob) {
  // 返回Promise对象,包裹异步逻辑
  return new Promise((resolve, reject) => {
    const gridFSBucket = new mongoose.mongo.GridFSBucket(conn.db),
          writeStream = gridFSBucket.openUploadStream(getAudioName())

    // 监听流关闭事件,此时文件已完全写入GridFS
    writeStream.on('close', (file) => {
      console.log("saveAudioToGridFS.close-block")
      const fileId = writeStream.id.toString();
      console.log("ID=", fileId)
      resolve(fileId); // 将文件ID传递给调用端
    });

    // 监听错误事件,传递错误信息
    writeStream.on('error', (error) => {
      console.log("saveAudioToGridFS.error-block")
      reject(error);
    });

    console.log("TRACE 1 : before createReadStream.")
    streamifier.createReadStream(audioBlob).pipe(writeStream)
    console.log("TRACE 2 : after createReadStream.")
  });
}

2. 在调用端使用await获取异步结果

路由回调已经是async函数,直接用await等待saveAudioToGridFS的结果即可:

server.post('/upload', async (req, res) => {
  try {
    if (!req.body.audio) {
      return res.status(400).json({message: 'No audio data uploaded.'});
    }

    console.log("Before call to saveAudioToGridFS")
    const audioBuffer = Buffer.from(req.body.audio, 'base64'),
          // 用await等待Promise返回结果
          fileId = await saveAudioToGridFS(audioBuffer);

    console.log("fileId=", fileId) // 现在能正确获取到文件ID了

    // 创建新记录对象
    const newRec = new AppCollectn({
      channelID:req.body.channel,
      voiceRecordID:fileId,
      timeStamp: new Date().getTime()
    });

    // 插入数据库
    await newRec.save();

    // 省略其他代码
    res.json({fileId});
  } catch (error) {
    console.error(error);
    res.status(500).json({
      message: 'An error occurred during upload.',
      error: JSON.stringify(error)
    });
  }
});

修复说明

  • 原代码中resolve和reject没有绑定到任何Promise上下文,无法传递结果;包装成Promise后,这两个方法才有了正确的回调上下文。
  • 流的finish和close事件无需重复监听,close事件在文件元数据也写入完成后触发,更适合作为完成标志。
  • 调用端用await等待Promise完成,确保后续代码能拿到正确的fileId再执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:57:35