I am writing a lyrics app, that saves a song book and the songs in that book to an SQL lite database. I am mapping through an array of books and calling an API to save the book’s songs.
I want the saveBook() function to fully complete before moving on to the saveBookSong() function. I have tried async await but it is not working. Any help would be greatly appreciated,
Thanks, Sam
useEffect( () => {
Books.map ((book) =>{
saveBook(book)
saveBookSong(book.songId.toString())
})
function saveBook(book) {
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)
}
);
});
}
function saveBookSong(id) {
axios
.get(`songs/${id}`)
.then((bookSong) => {
bookSong.data.forEach((song) => {
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,
],
() => {
}
);
});
});
})
.catch((err) => {
console.log(err);
});
}
2
Answers
If I’m not mistaken .map() is not async aware. So I would suggest two solutions to your problem:
1)
In this case you go with then after first function is executed.
2)
You can go with async for loop which will wait for executing first task before moving to another one
I’m assuming you want all the books to be saved in parallel. I would do this:
Alright, but you can’t simply
await
saveBook
andsaveBookSong
because they are notasync
functions. Let’s move forward.Under the hood, async functions are just functions that return promises. We can actually
await
any promise. Therefore, you can makesaveBook
andsaveBookSong
awaitable by wrapping them in promises, like this:EDIT:
The second function requires a bit extra caring because, like you pointed out, it contains a loop. However, that’s not really different from the top-level
.map
function that you had. Here’s my (untested) suggestion, hopefully you can work from here. I splitted the function in two, to make it more understandable: