Reputation: 499
I am receiving a list of books from a database as a Promise.
If the initial list of books is successfully loaded, the books are further processed by passing them to a utility function.
Inside the utility function is a forEach loop which loops over each initial book, makes an async call to get additional information, creates a new book object and adds it to an array of new books (called updatedBooks).
Problem: I don't know how to wait until the forEach loop is finished with every book and how to return the array of new books.
Currently, I only get one updated book instead of all
This is my current structure
controller.find(req.query)
.then(function (entities) {
awsUtil.addInfo(entities)
.then(function (updatedBooks) {
res.json({
confirmation: "success",
result: updatedBooks
})
})
.catch(function (err) {
res.json({
confirmation: "fail",
message: err
})
})
})
.catch(function (err) {
res.json({
confirmation: "fail",
message: err
})
})
Function to get the initial books from MongoDB
find: function (params) {
return new Promise(function (resolve, reject) {
Book.find(params, function (err, books) {
if (err) {
reject(err)
return
}
console.log("Org. Books List: ", books)
resolve(books);
})
})
}
Utility function to get additional information and return a new array of books
addInfo: function (books) {
return new Promise(function (resolve, reject) {
let updatedBooks = [];
books.forEach(function (book) {
client.itemLookup({ //Call Amazon API to get book info
idType: 'ISBN',
itemId: book.isbn,
responseGroup: 'ItemAttributes,Images'
})
.then(function (results) {
const updatedBook = {
// The additional info from result gets added here
}
updatedBooks.push(updatedBook);
}).catch(function (err) {
console.log(err);
reject(err)
});
})
resolve(updatedBooks) //Return the array of new books
})
}
Upvotes: 6
Views: 5283
Reputation: 318182
Modify the addInfo
method so it stores the promises in an array, and return Promise.all
instead, which will resolve when all the promises have resolved.
Assuming your methods returns a promise, and it looks like they do, something like
addInfo: function(books) {
let promises = books.map(function(book) {
return client.itemLookup({
idType : 'ISBN',
itemId : book.isbn,
responseGroup : 'ItemAttributes,Images'
}).then(function(results) {
return {
// The additional info from result gets added here
}
});
})
return Promise.all(promises); // catch errors where you call "addInfo"
}
Upvotes: 5