简体   繁体   English

在forEach循环中等待诺言

[英]Wait for promise in a forEach loop

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 ). 实用程序函数中有一个forEach循环,该循环遍历每本初始书,进行异步调用以获取更多信息,创建新书对象,并将其添加到新书数组(称为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. 问题:我不知道如何等待每本书的forEach循环完成以及如何返回新书的数组。

Currently, I only get one updated book instead of all 目前,我只收到一本更新的书,而不是全部

My ultimate goal is to have the list of updated books in the res.json() object 我的最终目标是在res.json()对象中拥有更新书籍的列表

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 从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
    })
}

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. 修改addInfo方法,使其将诺言存储在数组中,然后返回Promise.all ,当所有诺言都解决后, Promise.all将解决。

Assuming your methods returns a promise, and it looks like they do, something like 假设您的方法返回了一个Promise,看起来像他们做的那样,

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"
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM