如何在Redux中实现SQLite异步请求,避免加载状态早于数据库插入完成
问题解决
在Redux中完全可以实现SQLite异步请求,你遇到的dispatch(onLoading(false))提前触发的问题,核心是saveSQL方法内部的数据库操作没有正确封装为可等待的Promise,导致外层的await没有真正等到操作执行完成就继续往下走了。
问题根因
你当前使用的SQLite库(多数为React Native场景的SQLite库)的db.transaction和tx.executeSql默认是回调模式,你写的await db.transaction(async (tx) => {})并不会等待内部executeSql的回调执行完成,相当于外层的await dispatch(saveSQL(...))没有捕获到异步操作的完成状态,直接执行后续代码。
修复方案
1. 重写saveSQL,手动封装Promise
确保数据库操作完成(成功/失败)后才变更Promise状态,让外层的await可以正确等待:
export const saveSQL = (sql: string, params: any[] = []) => { return async (dispatch: Dispatch<ProblematikyInterface>) => { return new Promise((resolve, reject) => { db.transaction( (tx) => { tx.executeSql( sql, params, (tx, results) => { dispatch({ type: 'LOAD_PROBLEMATIKY', payload: [] }); console.log('Saved'); resolve(results); }, (tx, error) => { // SQL执行失败抛出错误 reject(error); return false; } ); }, (transactionError) => { // 事务执行失败抛出错误 reject(transactionError); } ); }); }; };
2. 同步修改saveProblematiky方法
和saveSQL逻辑一致,对saveProblematiky也做相同的Promise封装,否则循环里的await dispatch(saveProblematiky(...))也不会生效。
3. 优化插入逻辑,避免SQL注入
不要直接拼接SQL字符串,改用参数化查询,修改后的循环插入逻辑如下:
for (const insert of inserts) { await dispatch( saveProblematiky( `INSERT INTO 'bepr_problematiky' VALUES(?, ?, ?, ?, ?);`, [insert.id, insert.uid, insert.title, insert.text, insert.file] ) ); }
前置检查
确保你的Redux已经配置了redux-thunk中间件,支持返回函数的异步Action,否则异步Action本身不会生效。
内容的提问来源于stack exchange,提问作者Roman Šimr
相关产品推荐
相关产品推荐

