React Native实现saveBook完成后再执行saveBookSong的问题求助
解决SQLite保存歌本后再保存对应歌曲的异步执行问题
你的代码核心问题在于saveBook和saveBookSong都是异步操作,但没有返回Promise,导致async/await无法生效。要实现"歌本保存完成后再执行歌曲保存"的逻辑,需要将两个函数改造为返回Promise的异步函数,再通过async/await严格控制执行顺序。
1. 改造saveBook为返回Promise的函数
将SQLite的回调式异步操作封装成Promise,确保歌本写入数据库完成后才触发后续逻辑:
function saveBook(book) { return new Promise((resolve, reject) => { db.transaction((tx) => { tx.executeSql( `INSERT INTO books (id, description, img, name, song_id) VALUES (?, ?, ?, ?, ?)`, [book.id, book.description, book.img, book.name, book.songId], () => { console.log("Saved!!", book.id); resolve(); // 保存成功后标记Promise完成 }, (tx, error) => { console.error("歌本保存失败:", book.id, error); reject(error); // 保存失败时抛出错误 } ); }, (error) => { console.error("歌本事务执行失败:", error); reject(error); }); }); }
2. 改造saveBookSong为返回Promise的函数
不仅要等待API请求完成,还要确保当前歌本的所有歌曲都写入数据库后才完成Promise:
function saveBookSong(id) { return new Promise((resolve, reject) => { axios .get(`songs/${id}`) .then((bookSong) => { // 将每个歌曲的保存操作转为Promise const songSavePromises = bookSong.data.map(song => { return new Promise((songResolve, songReject) => { db.transaction((tx) => { tx.executeSql( `INSERT INTO songs (id, book, book_id, data, int_song_number, lang, search_title, song_number, title, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ song.id, song.book, song.bookId, song.data, song.intSongNumber, song.lang, song.searchTitle, song.songNumber, song.title, song.url, ], () => songResolve(), (tx, error) => { console.error("歌曲保存失败:", song.id, error); songReject(error); } ); }, (error) => { console.error("歌曲事务执行失败:", error); songReject(error); }); }); }); // 等待当前歌本的所有歌曲保存完成 Promise.all(songSavePromises) .then(() => resolve()) .catch(err => reject(err)); }) .catch((err) => { console.error("获取歌曲列表失败:", err); reject(err); }); }); }
3. 在useEffect中用async/await控制执行顺序
注意不要直接在useEffect回调中写async,而是内部定义异步函数并调用;用for...of遍历歌本数组,确保每个歌本的保存与歌曲保存是串行执行的:
useEffect(() => { const saveAllData = async () => { for (const book of Books) { try { await saveBook(book); // 等待当前歌本保存完成 await saveBookSong(book.songId.toString()); // 再执行对应歌曲的保存 } catch (error) { console.error("歌本处理失败:", book.id, error); // 若需要遇到错误就中断所有操作,取消下面的注释 // throw error; } } }; saveAllData(); }, [Books]); // 依赖数组加入Books,确保数组更新时重新执行
内容的提问来源于stack exchange,提问作者Samuel Yarasani
相关产品推荐
相关产品推荐

