Turso异步事务中console.log无输出及插入ID获取失败问题
单事务下Turso边缘数据库批量插入后获取ID异常问题
需求与问题
核心需求
- 向数据库插入数据并获取对应自增ID;
- 插入关联数据组并批量获取各自ID;
- 将前两步的ID插入关联映射表。
异常表现
该流程在SQLite单事务中可正常运行,但切换到Turso边缘数据库后出现以下问题:
- 使用
forEach循环处理关联数据时,函数内console.log(insertedProponentIds)输出空数组,但接口最终能返回有效ID数组; - 改用
for of循环后,触发「Invalid insertedProponentId data」错误,无法正确获取插入ID,导致关联映射表插入操作无法执行。
原始代码
function buildRouter(env: Env): RouterType { const router = Router(); router.post("/api/main-form", async (request) => { const db = buildDB(env) const formData = await request.json(); const loadedFormInfo: any = await db.transaction(async (tx) => { // 插入主表并获取ID const insertedFormId: any = tx.insert(formDataTable) .values({ dateOption: formData.dateOption, timeZone: formData.timeZone, utcTime: new Date(formData.utcTime), localTime: formData.localTime, title: formData.title, tag: formData.tag, latitude: formData.latitude, longitude: formData.longitude, createdAt: new Date() }) .returning({formId: formDataTable.id}); let formId = await insertedFormId.values(); formId = formId[0].id // 插入关联数据并收集ID const proponentsData: Proponent[] = formData.proponents; let insertedProponentIds: Number[] = []; proponentsData.forEach(async proponent => { let insertedProponentId = tx.insert(proponentsTable) .values({ formId: formId, team: proponent.team, name: proponent.name, email: proponent.email, createdAt: new Date() }).returning({proponentId: proponentsTable.id}); let proponentId = await insertedProponentId.values(); proponentId = proponentId[0].id; insertedProponentIds.push(proponentId); }); console.log(insertedProponentIds) // 输出空数组 return insertedProponentIds // 接口返回有效数组 // 第三步插入关联映射表的代码位置 // }); console.log('outside: ', loadedFormInfo) const responseBody = JSON.stringify( {'return_val': loadedFormInfo} ); const response = new Response(responseBody, { status: 200, headers: { 'Content-Type': 'application/json' } }); return response; }); router.all("*", () => new Response("Not Found.", { status: 404 })); return router; };
尝试修改后的代码
// 插入关联数据并收集ID const proponentsData: Proponent[] = formData.proponents; let insertedProponentIds: Number[] = []; for (const proponent of proponentsData) { try { const insertedProponentId = await tx.insert(proponentsTable) .values({ formId: formId, team: proponent.team, name: proponent.name, email: proponent.email, createdAt: new Date() }) .returning({ proponentId: proponentsTable.id }); if (insertedProponentId && insertedProponentId[0] && insertedProponentId[0].id) { const proponentId = insertedProponentId[0].id; insertedProponentIds.push(proponentId); } else { console.error("Invalid insertedProponentId data:", insertedProponentId); } } catch (error) { console.error("Error inserting proponent:", error); } } console.log(insertedProponentIds) return insertedProponentIds
报错信息
[mf:inf] POST /api/main-form 500 Internal Server Error (757ms) ⎔ Reloading local server... [mf:inf] Updated and ready on http://127.0.0.1:8787/ Invalid insertedProponentId data: SQLiteInsert { session: _LibSQLSession, dialect: SQLiteAsyncDialect, config: Object, run: , all: ... } Invalid insertedProponentId data: SQLiteInsert { session: _LibSQLSession, dialect: SQLiteAsyncDialect, config: Object, run: , all: ... } Array(0) [ ] outside: Array(0) [ ] [mf:inf] POST /api/main-form 200 OK (49ms)
问题根源与解决方案
问题根源
- forEach异步执行问题:forEach不会等待内部async函数执行完成,
console.log执行时数组还未被填充,但事务最终会等待所有异步操作结束,因此接口能返回正确结果; - 遗漏
.values()调用:Turso插入操作返回的是SQLiteInsert对象,必须调用.values()才能获取实际返回数据,之前直接判断对象结构的逻辑错误; - 字段名匹配错误:
.returning({proponentId: proponentsTable.id})定义的返回字段是proponentId,而非id,之前的代码错误访问了id字段。
修正后的代码
// 插入关联数据并收集ID const proponentsData: Proponent[] = formData.proponents; let insertedProponentIds: Number[] = []; for (const proponent of proponentsData) { try { // 关键:调用.values()获取插入后的返回数据 const insertedProponentResult = await tx.insert(proponentsTable) .values({ formId: formId, team: proponent.team, name: proponent.name, email: proponent.email, createdAt: new Date() }) .returning({ proponentId: proponentsTable.id }) .values(); // 匹配.returning定义的字段名proponentId if (insertedProponentResult?.[0]?.proponentId) { insertedProponentIds.push(insertedProponentResult[0].proponentId); } else { console.error("Invalid insertedProponentId data:", insertedProponentResult); } } catch (error) { console.error("Error inserting proponent:", error); } } console.log(insertedProponentIds) // 此处可执行关联映射表插入操作,示例: // await tx.insert(关联映射表).values( // insertedProponentIds.map(id => ({ formId, proponentId: id })) // ); return insertedProponentIds
内容的提问来源于stack exchange,提问作者avnav99
相关产品推荐
相关产品推荐

