React Native:db.transaction内更新数组后外部无法读取的疑问
React Native SQLite异步操作后数组无法正确访问的解决方案
你遇到的核心问题是SQLite的数据库操作是异步执行的:db.transaction和内部的tx.executeSql不会阻塞后续代码运行,外部读取数组的逻辑会先于数据库查询的回调函数执行,所以此时rcpts还是初始的空数组。下面是具体的解决方法:
方法1:用Promise封装操作,配合async/await
把数据库查询逻辑封装成返回Promise的函数,通过async/await让代码按预期顺序执行:
let rcpts = [] const db = SQLite.openDatabase('digit.db'); // 封装数据库查询为Promise函数 function fetchReceipts() { return new Promise((resolve, reject) => { db.transaction(tx => { tx.executeSql( "SELECT id,date, agentNo, custName, custNo, paidAmount, custBalance, payMode, revGroup FROM tblRcpt ORDER BY Id DESC LIMIT 100 ", null, (tx, result) => { const rcptlist = []; const len = result.rows.length; if (len > 0) { for (let i = 0; i < len; i++) { const item = result.rows.item(i); rcptlist.push({ rcptNo: item.id, rcptdate: item.date, agentNo: item.agentNo, custName: item.custName, custNo: item.custNo, paidAmount: item.paidAmount, custBalance: item.custBalance, payMode: item.payMode, revGroup: item.revGroup }); // 注意:删除原代码中多余的i++,否则会跳过一半数据 } } resolve(rcptlist); }, (error) => { reject(error); } ); }); }); } // 用async/await调用异步操作 async function pushreceipts() { try { rcpts = await fetchReceipts(); Alert.alert("Data Push finished."); // 现在可以正常访问rcpts数组 console.log(rcpts.length); rcpts.forEach((item, index) => { console.log(`第${index+1}条收据:`, item); }); // 在这里执行fetch发送数据的逻辑 } catch (error) { Alert.alert(`查询失败:${error.message}`); } }
方法2:把后续操作直接放到回调函数内部
既然回调函数是数据库查询完成后才触发的,所有需要使用rcpts的逻辑都可以直接放在这个回调里:
let rcpts = [] const db = SQLite.openDatabase('digit.db'); function pushreceipts(){ let rcptlist =[]; db.transaction(tx=>{ tx.executeSql( "SELECT id,date, agentNo, custName, custNo, paidAmount, custBalance, payMode, revGroup FROM tblRcpt ORDER BY Id DESC LIMIT 100 ", null, (tx,result)=>{ const len = result.rows.length; if (len>0){ for(let i =0;i<len;i++){ const item = result.rows.item(i); rcptlist.push({ rcptNo : item.id, rcptdate : item.date, agentNo : item.agentNo, custName : item.custName, custNo : item.custNo, paidAmount : item.paidAmount, custBalance : item.custBalance, payMode : item.payMode, revGroup : item.revGroup }); // 删除原代码中多余的i++,避免跳过数据 } } rcpts = rcptlist; Alert.alert("Data Push finished.") // 把需要使用rcpts的逻辑移到这里 console.log(rcpts.length); rcpts.forEach((item, index) => { console.log(`rcpts数组长度:${rcpts.length},第${index+1}条数据`, item); }); // 在这里执行fetch发送数据的逻辑 }, (error) =>{ Alert.alert(`查询错误:${error.message}`); } ); }); }
额外注意事项
- 原代码的for循环中多了一行
i++,这会导致每次循环i自增2,直接跳过一半的数据,必须删除。 - 错误处理时尽量输出
error.message,而非直接弹出error对象,更便于排查问题。
内容的提问来源于stack exchange,提问作者Bineesh Kumar
相关产品推荐
相关产品推荐

