简体   繁体   中英

Result of a promise inside of forEach

I'm trying to rewrite the code of one my project with the promise (Q). I don't know how to take the result of a chain of promises inside a foreach loop:

var resProducts = [];
products.forEach(currProduct) {
     Stock.saveNewStock(currProduct)
        .then(function(res1) {
            Product.saveNewProduct(currProduct)
               .then(function(res2) {
                  resProducts.push(res2);
                  Product.addStockToProduct(res1,res2)
               })
         })
         .catch(function(err) {
             console.log(err)
         })
});
console.log(resProducts);

I see that every time the log stamps an empty array, so how I can resolve it?

You should always return all promises , and you're forgetting to in several places here.

If you can use => arrow functions, then these implicitly return, which avoids forgetting.

Instead of forEach which ignores return values, use map and return results into an array. This does the work in parallel as well:

Promise.all(products.map(product => Stock.saveNewStock(product)
  .then(res1 => Product.saveNewProduct(product)
    .then(res2 => Product.addStockToProduct(res1, res2)
      .then(() => res2))))
.then(resProducts => console.log(resProducts))
.catch(err => console.error(err));

The nesting here is intentional, to access res1 and res2 together.

How about this?

// Define iterator function
function doThingsWithProducts(productsLeft, resProducts) {
    if (productsLeft.length === 0) { return resProducts }
    else {
        var currProduct = productsLeft.shift(), res1, res2;
        return Stock.saveNewStock(currProduct)
        .then(function(res) {
            res1 = res;
            return Product.saveNewProduct(currProduct)
        })
        .then(function(res) {
            res2 = res;
            resProducts.push(res2);
            return Product.addStockToProduct(res1, res2)
        })
        .then(function() {
            return doThingsWithProducts(productsLeft, resProducts)
        })
        .catch(function(err) {
            console.log(err);
        })
    }
}

// resProducts is available in the result of the function
doThingsWithProducts(products, [])
.then(function(resProducts) {
    console.log(resProducts);
})

Something like this is that you need?

var defer = $q.defer();
            var promises = [];
            var resProducts = [];
            var errorCallback = function (e) {

              defer.reject();
            };

           products.forEach(currProduct) {

                promises.push(function () {
                    Stock.saveNewStock(currProduct)
                        .then(function(res1) {
                            return Product.saveNewProduct(currProduct)
                        .then(function(res2) {
                            resProducts.push(res2);
                            Product.addStockToProduct(res1,res2)
                   })
             })
             .catch(function(err) {
                 console.log(err)
             })
                }


                );
              }

            });
            return $q.all(promises);

Use Array.map() in combination with Q.all()

var resProducts = [];

Q.all(products.map(function (currProduct) {
        // Return promise that Q.all() can resolve.
        return Stock.saveNewStock(currProduct)
            .then(function (res1) {
                // Make sure you always return promises when they
                // are in a chain so  the chain will work correctly.
                return Product.saveNewProduct(currProduct)
                    .then(function (res2) {
                        resProducts.push(res2);
                        return Product.addStockToProduct(res1, res2)
                    })
            })
    }))
    .then(function (products) {
        // Products here is the array of resolved promises.

        // and here your array will be full.
        console.log(resProducts);
    })
    .catch(function (err) {
        console.log(err)
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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