skip to Main Content

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)+'}');
});
}

2

Answers


  1. What I assume you want:

    1. You already have some dataArray
    2. You wish to request additional data in parallel from server for each item
    3. After all requests are completed you wish to process results

    $.getJSON method returns jqXHR object, which implements the Promise interface, so you can use it either this way:

    $.getJSON(someUrl).then(result => {
        // do something with result
    });
    

    or this way (inside async function):

    const result = await $.getJSON(someUrl);
    // do something with result
    

    Next step is to make your item processing async:

    async function processItem(item) {
        return await $.getJSON(item.url);
    }
    

    And process whole array in parallel:

    async function processArray(array) {
        const promises = array.map(processItem);
        return await Promise.all(promises);
    }
    

    Note that Promise.all resolves to an array with results for each item, and order of results is the same as order in initial array of promises.

    Below is complete snippet that processes array asynchronously and waits until processing is finished. Note that I created asyncGetJson placeholder function in my snippet to simulate real server request with timeout:

    // Helper function to simulate random request timeout
    function getRandomInt(min, max) {
      min = Math.ceil(min);
      max = Math.floor(max);
      return Math.floor(Math.random() * (max - min) + min);
    }
    
    /**
     * Not a real request, just a placeholder
     * This function multiplies n by 2 and returns it after random timeout
     */
    function asyncGetJson(n) {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(n * 2);
        }, getRandomInt(500, 2000));
      });
    }
    
    async function processItem(item) {
      return await asyncGetJson(item);
    }
    
    async function processArray(dataArray) {
      const promises = dataArray.map(processItem);
      return await Promise.all(promises);
    }
    
    async function init() {
      const dataArray = [1, 2, 3];
    
      console.log('Start');
      const result = await processArray(dataArray);
      console.log(result);
      console.log('Done');
    
      // Here should be your logic that works with results from the server
    }
    
    init();
    Login or Signup to reply.
  2. 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
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search