0

First of all I'm aware of the multiple topics concerning this issue. But I just can't find the reason why it doesn't work in my case.

I'm trying to find the nearest highest value qty in an array. This array is dynamically created. So in below example the current value/quantity is 17. I want to return from the array the object containing qty: 60.

Whatever I try the output is undefined. I just can't see why that is.

<div class="product" data-url="some-url-to-json" data-quantity="17">
  ....
</div>

$(function(){

 $('#form-pagecart .product').each(function(){
   var url = $(this).data('url') + '?format=json';
   var cur_qty = $(this).data('quantity')
   var highestArray= []
   $.getJSON(url, function(data){
     $.each(data.product.discounts, function(index, disc) {
       highestArray.push({ qty: parseInt(disc.quantity), price: disc.price.price_incl, price_excl: disc.price.price_excl })
    });
   });

   /* things I tried ======> */
   var output = highestArray.slice().reverse().find(({ qty }) => qty <= cur_qty);
   var nearest = highestArray.sort(function(a, b){ 
        return Math.abs(a.qty - cur_qty) - Math.abs(b.qty - cur_qty)
   })[0];
   console.log(output, nearest)
 });

When I console.log highestArray I get:

[
  {
    "qty": 15,
    "price": 18.1379,
    "price_excl": 14.99
  },
  {
    "qty": 60,
    "price": 16.3229,
    "price_excl": 13.49
  },
  {
    "qty": 120,
    "price": 15.1129,
    "price_excl": 12.49
  },
  {
    "qty": 240,
    "price": 14.5079,
    "price_excl": 11.99
  }
]

Why keeps console.log returning undefined then for output and nearest?

I aslo tried using a function like:

changePrice(highestArray, cur_qty)

function changePrice(array,num){
 var output = array.slice().reverse().find(({ qty }) => qty <= num);
 if(output){
    $('.price .price-new i').text(output['price'])
    $('.price .vat i').text(output['price_excl'])
  }
}
Meules
  • 1,140
  • 4
  • 20
  • 60
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – freedomn-m May 19 '20 at 16:27
  • Things you should have tried: `console.log(highestArray)` just before you use it, `$.getJSON` runs asynchronously, so the `$.each(..push..)` runs *after* your `things I tried` – freedomn-m May 19 '20 at 16:28
  • related: both your "what I tried" return the qty:15 entry (when highestArray isn't empty) https://jsfiddle.net/2n73urcm/ but you state you expect qty:60. Not really clear what "highest nearest values" is for 17 giving 60 (wouldn't that be lowest higher value?) – freedomn-m May 19 '20 at 16:31
  • @freedomn-m: Well you are correct. What I mean is "the next value". So when current value is 17 then the next value in the array is 60. So I want to return the object with 60. When current value is eg. 10 then the next value would be 15. But also when I have 15 as value then the next value that should return is 60 – Meules May 19 '20 at 16:39
  • no worries - that's not really the issue, just noticed it when having a look. Your issue is the async of `$.getJSON` – freedomn-m May 19 '20 at 16:49
  • @freedomn-m: Yes that's correct, i see now. However can you help to return the next number instead of the closest number? I'll adjust question :) – Meules May 19 '20 at 16:56
  • I recommend you ask a new question TBH as this one is about the `undefined` – freedomn-m May 19 '20 at 16:57
  • You can use `.filter` to reduce the array set first then sort and get first: `var next = highestArray.filter(({ qty }) => qty > cur_qty).sort()[0];` (probably want your extended `sort` in there) – freedomn-m May 19 '20 at 17:01

1 Answers1

1

Maybe the server has not returned the JSON you need at the moment you try to get the highest value.

Try something like this:


$('#form-pagecart .product').each(function(){
   var url = $(this).data('url') + '?format=json';
   var cur_qty = $(this).data('quantity')
   var highestArray= []
   $.getJSON(url, function(data){
     $.each(data.product.discounts, function(index, disc) {
       highestArray.push({ qty: parseInt(disc.quantity), price: disc.price.price_incl, price_excl: disc.price.price_excl 
     });
     // Do it inside the callback, so you can be sure that the
     // JSON is already there.
     var output = highestArray.slice().reverse().find(({ qty }) => qty <= cur_qty);
   });

});

freedomn-m
  • 21,261
  • 4
  • 28
  • 53
Angel González
  • 108
  • 1
  • 4
  • 1
    Hi, this is a fine answer. However, in this case, this question (or variants of it) gets asked at least 10 times a day (anecdotal) and there's a good answer that explains the issue in detail (there's another similar answer that also explains in detail, I always use the one above). Rather than repeat the answer every time, we provide a link and vote-close as a duplicate. You'll soon have enough rep to also vote close. You might find this of interest: https://stackoverflow.com/help/privileges – freedomn-m May 19 '20 at 16:47