0

In my Angular project i have a Promise that returns an array of Products:

{"Products":[{"Code":123},{"Code":456}]}

Then for each product code, i must call two other promises that return Price and Quantity respectively.

I use ui-router and my current implementation code in my resolve is below :

$stateProvider.state('root.products', {
                    abstract: true,
                    url: '/products',
                    template: '<div data-ui-view=""></div>',
                    resolve: {
                        products: ['ProductsService', function (ProductsService) {
                            return ProductsService.getProducts()
                                .then(function (response){
                                    var data = response.data;
                                    return data.Products.map(function (product) {

                                        var viewModelProduct = {};

                                        angular.copy(product, viewModelProduct);

                                        //get Price for Each Product
                                        ProductsService.getPrice(product.Code)
                                            .then(function (response) {
                                                viewModelProduct.Price = response.data.Info.Price;
                                            })

                                        //get Quantity for Each Product
                                        ProductsService.getQuantity(product.Code)
                                           .then(function (response) {
                                               viewModelProduct.Quantity = response.data.Info.Quantity;
                                           })

                                        return viewModelProduct;
                                    });
                                });
                                }]
                        }
                        })

It works but my question is if i can write it better. I read about the use of $q and $q.all but I don't really know how to use them. Is there any way i can write the above code, better and safer??

Thanks in advance for your help!

scniro
  • 16,844
  • 8
  • 62
  • 106
Ricky Stam
  • 2,116
  • 21
  • 25

2 Answers2

1

It works but my question is if i can write it better.

Yes. You can write promise chain. The advantage is: Error propagates, you can catch it on the end of the chain and its not piramide like async call in Javascript

See flow example bellow:

enter image description here

[EDIT]

if the order is not critical you can use $q.all that gets list of promises and notify you when all of them resolved successfully.

It should be something like:

       $q.all([
            ProductsService.getPrice(product.Code),
            ProductsService.getQuantity(product.Code)
           ])
            .then(function(result){

            viewModelProduct.Price   = result[0].data.Info.Price;
            iewModelProduct.Quantity = result[1].data.Info.Quantity; 

          }, function(error) {
              alert(error.message);
          });

or even:

     var promises = [];
     promises.push(ProductsService.getPrice(product.Code));
     promises.push(ProductsService.getQuantity(product.Code));

       $q.all(promises).then(function(result){

            viewModelProduct.Price   = result[0].data.Info.Price;
            iewModelProduct.Quantity = result[1].data.Info.Quantity; 

          }, function(error) {
              alert(error.message);
          });
Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
1

If you need to execute promises one after other you will use chains like Maxim mentioned. More one topic:

If you need to execute more promises and then resolve it you will use "$q.all".

See documenttion:

UPDATE

Not sure if I understand well but you should use combination of q.all and chaining. Again, sorry if I didn't understand you well.

var p1 = ProductsService.getPrice(product.Code)
 .then(function (response) {
    return response.data.Info.Price;
 });

var p2 = ProductsService.getQuantity(product.Code)
         .then(function (response) {
         return response.data.Info.Quantity;
 });


    return $q.all([p1,p2]); // next "then" will get array with price and quantity respectively. 
Andrej Kaurin
  • 11,592
  • 13
  • 46
  • 54
  • I've read about promise chaining here http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/ but all the examples i find in general have only one object returning, i'm confused how to chain the two promises forEach Product – Ricky Stam Jul 07 '14 at 15:13