Search code examples
jqueryajaxpromise.when

Multi AJAX requests inside a loop and building an array


I'm completely stuck. I want to accomplish the following: Update the shopping cart with the correct price agreements while logging in and out.

  1. Get current cartlines from LocalStorage (successful)
  2. With every cartline an AJAX request (getJSON for example) to get back the new data that applies at that moment. (Success)
  3. Create a new object and save the new data.
  4. Add the new object to the array.
  5. When all AJAX requests are ready and the new array (new_cart) is completely filled, then push it to LocalStorage again.

Below my script. I hope someone can help me on my way.

function sync() {

// Read LocalStorage
try {
  var dataArray = JSON.parse(getLocalStorage('cartarray'));
}
catch (err) {
  var dataArray = null;
}

ary1 = dataArray.cartlines;

var keys = Object.values(ary1);
        
        
// Delete LocalStorage
// unsetLocalStorage('cartarray');
        
new_cart1 = [];
$.each( keys, function( index, value ){  
    var itemUrl = "https://" + window.location.hostname + "/search/?sku=" + value.sku;
    var value1 = value.quantity;
    var p = $.getJSON(itemUrl);

    p.then(function(data) {
        var obj = {};
        
        // Add items
        obj['sku'] = data.results[0].sku;
        obj['quantity'] = value1;
        obj['price'] = data.results[0].price;
        obj['title'] = data.results[0].product_title;
        obj['img'] = data.results[0].img;
        obj['url'] = data.results[0].url;
        obj['internalSku'] = data.results[0].sku;

        // Return obj
        return obj;
    });
  
    // Add to object to array.
    new_cart1.push(obj);
});
        

$.when.apply($, new_cart1).then(function() { 
    var keys1 = new_cart1;
    var cartarray1 = [];
            
    for (var key of keys1) {
        console.log(key);
        if(key.quantity >= 1){
            cartarray1.push({
                sku: key.sku, 
                title: key.title,
                price: key.price,
                img: key.img,
                url: key.url,
                quantity: key.quantity,
                internalSku: key.internalSku,
                // custom: key.custom
            }); 
        }   
    }
    // setLocalStorage('cartarray', '{"cartId": "","cartlines":'+JSON.stringify(cartarray)+'}');
});
}

Solution

  • This is all much simpler if you think of each item being a single async method

    async function processItem(value) {
        var itemUrl = "https://" + window.location.hostname + "/search/?sku=" + value.sku;
        var data = await $.getJSON(itemUrl);
    
        return {
           sku: data.results[0].sku,
           quantity: value.quantity,
           price: data.results[0].price,
           title: data.results[0].product_title,
           img: data.results[0].img,
           url: data.results[0].url,
           internalSku: data.results[0].sku
        };        
    }
    

    Then waiting for them all is as simple as doing Promise.all on the result of a map to get the values. The below runs them all concurrently and waits for all results to complete.

    async function execute(){ 
        var dataArray = JSON.parse(getLocalStorage('cartarray'));
        var values = Object.values(dataArray.cartlines);
        var new_cart1 = await Promise.all(values.map(processItem));
    
        // do something with new_cart1 which is an array of 
        // the objects returned from processItem
    }