React Native中如何将网络图片转Blob存入SQLite数据库?
解决方案:React Native 网络图片转Base64并存入SQLite数据库
一、修复图片转换函数的返回值问题
你的convertImageToBase64函数没有正确返回转换结果,因为FileReader的onload是异步回调,原代码未将其包装为Promise,导致async函数无返回值。修改后的函数如下:
export const convertImageToBase64 = async (imgUrl) => { const response = await fetch(imgUrl); const blob = await response.blob(); return new Promise((resolve) => { const fr = new FileReader(); fr.readAsDataURL(blob); fr.onload = () => { resolve(fr.result); // 正确返回Base64字符串 }; }); };
修改说明:
- 用
await替代then嵌套,简化异步逻辑 - 将
FileReader的异步操作包装为Promise,确保函数能返回转换后的结果
二、解决SQLite事务中的异步插入问题
插入时图片字段为空的核心原因:tx.executeSql是异步API但不返回Promise,map里的async函数会让循环提前结束,事务可能在所有图片转换和插入完成前就提交了。需要把每个操作包装为Promise并等待全部完成:
// 表创建建议只在初始化时执行一次 db.transaction((tx) => { tx.executeSql( "CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, img BLOB, done INTEGER)" ); }); // 封装异步插入逻辑 const insertItems = async (result) => { await new Promise((resolve, reject) => { db.transaction(async (tx) => { // 用for...of替代map,确保逐个等待异步操作完成 for (const item of result) { try { const base64Img = await convertImageToBase64(imgUrl); // 把tx.executeSql包装为Promise,等待SQL执行完成 await new Promise((sqlResolve) => { tx.executeSql( "INSERT INTO items (name, img, done) VALUES (?,?,?)", [item.name, base64Img, item.done], (tx, results) => { console.log('插入成功,影响行数:', results.rowsAffected); sqlResolve(); }, (tx, error) => { console.error('插入失败:', error); sqlResolve(); // 可根据需求选择是否终止流程 } ); }); } catch (err) { console.error('图片转换失败:', err); } } resolve(); }, (error) => { reject(error); console.error('事务执行失败:', error); }); }); }; // 调用插入函数 insertItems(result);
修改说明:
- 用
for...of替代map:map会生成未等待的Promise数组,for...of配合await能确保每个插入操作完成后再进行下一个 - 包装
tx.executeSql为Promise:适配异步等待逻辑,避免SQL操作未完成就进入下一轮循环 - 事务整体包装为Promise:确保所有插入操作完成后再结束事务,避免数据不完整
三、额外注意事项
- 存储格式选择:SQLite的
BLOB字段可直接存储Base64字符串,若想节省空间,也可修改转换函数返回原始Blob数据存入 - 性能优化:图片数量较多时建议分批插入,避免一次性处理大量请求导致应用卡顿
- 错误处理:完善的异常捕获可避免单个图片处理失败导致整个插入流程中断
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

