Google Drive API调用报错await表达式无效引发竞态条件
问题根因
触发报错、await失效和竞态问题的核心原因有两个:
await仅对Promise/Thenable对象生效,编译器抛出'await' has no effect on this type of expression,说明当前调用的drive.files.create返回值不是Promise。绝大多数网上的Google Drive API教程默认基于googleapis@26及以上版本编写,这部分版本的SDK在不传回调参数时会默认返回Promise;如果本地安装的SDK版本低于26,接口默认是Node.js传统回调风格,直接加await不会有任何等待效果。- 函数结构存在逻辑漏洞:外层
writeFileFromPath声明为async函数,但内部定义run异步函数后直接调用run().catch(...),没有对run的执行加await,外层函数会在run执行到IO等待阶段时直接返回,完全等不到上传逻辑执行完成,直接触发竞态条件。
修复步骤
1. 解决await无效问题
优先升级本地googleapis依赖到官方支持Promise的稳定版本,在项目目录执行以下命令:
npm install googleapis@latest
升级完成后,所有Google服务接口在不传回调的场景下会默认返回Promise,await可正常工作。
如果项目存在依赖锁限制无法升级大版本,手动将回调风格的接口调用封装为Promise即可兼容:
// 旧版本SDK兼容写法 let driveResp = await new Promise((resolve, reject) => { drive.files.create({ supportsTeamDrives: true, resource: fileMeta, media: media, fields: 'id' }, (err, response) => { if (err) return reject(err); resolve(response); }) });
2. 修复函数结构的异步逻辑漏洞
移除无意义的嵌套run函数,直接在外层async函数内编写业务逻辑,避免异步调用脱离await的控制范围。修正后的完整函数参考:
// 注意需要提前引入fs依赖:const fs = require('fs'); async function writeFileFromPath(srcPath, dstFolderId, ext, fileName) { try { console.log("Using File Path: ", srcPath); if (!fileName) { fileName = srcPath.match(/[\w()-.]+\.[\w]+/g)[0]; } console.log("Using File Name: ", fileName); if (!ext) { ext = fileName.match(/[\w]+$/g)[0]; } const mimeType = mimeTypes[ext] || 'text/plain'; console.log("Using MIME Type: ", mimeType); const fileMeta = { name: fileName, parents: [dstFolderId] }; const media = { mimeType: mimeType, body: fs.createReadStream(srcPath) }; const driveResp = await drive.files.create({ supportsTeamDrives: true, resource: fileMeta, media: media, fields: 'id' }); if (driveResp.data?.id) { console.log(`Created file with id: ${driveResp.data.id}`) return { status: 200, statusText: `Created file with id: ${driveResp.data.id}` }; } console.log(`Failed to create file: ${driveResp}`) return { status: 400, statusText: `File was not created: ${driveResp}` }; } catch (e) { logger.addLog("googleDrive", "alert", "Unhandled Err: " + e); console.log("writeFileFromPath Error Caught: ", e.message); return e.message } };
验证标准
- 修复后编译器不再抛出await无效的提示
- 外部调用
writeFileFromPath时添加await接收返回值,会等待文件上传流程完全结束后再拿到结果,竞态问题消失
内容的提问来源于stack exchange,提问作者user3569450
相关产品推荐
相关产品推荐

