1

I am trying to make an external AJAX call to an API within a Jquery each loop.

Here is the code I have so far.

getStylesInfo(tmpMake, tmpModel, tmpModelYear, tmpSubmodel).done(function(data){
    var holder = [];

    $.each(styles, function(index, value) {
        var tempValue = value;
        var temp = getNavigationInfo(value.id);

        $.when(temp).done(function(){
            if(arguments[0].equipmentCount == 1){
                holder.push(tempValue);
                console.log(holder);
            }
        });
    });
});

console.log(holder);

function getStylesInfo(make, model, year, submodel){
    return $.ajax({
    type: "GET",
    url: apiUrlBase + make + '/' + model + '/' + year + '/' + 'styles?  fmt=json&' + 'submodel=' + submodel + '&api_key=' + edmundsApiKey + '&view=full',
   dataType: "jsonp"
});   


function getNavigationInfo(styleId){
    return $.ajax({
    type: "GET", 
    url: apiUrlBase + 'styles/' + styleId + '/equipment?availability=standard&name=NAVIGATION_SYSTEM&fmt=json&api_key=' + edmundsApiKey,
    dataType: "jsonp"
});   

The getStylesInfo() returns something similar to this. An array of objects with info about a car model.

var sampleReturnedData = [{'drivenWheels': 'front wheel drive', 'id': 234321}, {'drivenWheels': 'front wheel drive', 'id': 994301}, {'drivenWheels': 'rear wheel drive', 'id': 032021}, {'drivenWheels': 'all wheel drive', 'id': 184555}];  

I am trying to loop through the sampleReturnedData and use each id as a parameter in a different AJAX call with the getNavigationInfo() function.

I want to loop through the results and make a check. If it is true then I want to push the entire object to the holder array.

The problem is the console.log(holder) outside the function returns an empty array. The console.log(holder) within the if statement works properly.

I am not sure if this is a scope/hoisting issue or a problem with the way I am using deferreds?

I have read this question and many like it. They suggest to use either

async:false

Or to rewrite the code better. I have tried and used console debugger numerous times. I don't want to set it to false. I'm just unsure what exactly is going on.

I've also read up on hoisting via this article.

I believe it has to do with deferreds but I don't have enough JS knowledge to figure it out.

Thanks!

Community
  • 1
  • 1
swollavg
  • 911
  • 1
  • 6
  • 11

1 Answers1

3

I am not sure if this is a scope/hoisting issue or a problem with the way I am using deferreds?

In fact, it is both:

So what you should do is indeed to rewrite your code to use promises properly :-)

getStylesInfo(tmpMake, tmpModel, tmpModelYear, tmpSubmodel).then(function(data) {
    var holder = [];
    var promises = $.map(data.styles, function(value, index) {
        return getNavigationInfo(value.id).then(function(v){
            if (v.equipmentCount == 1)
                holder.push(value);
        });
    });
    return $.when.apply($, promises).then(function() {
        return holder;
    }); // a promise for the `holder` array when all navigation requests are done
}).then(function(holder) {
    console.log(holder); // use the array here, in an async callback
});
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375