2015-04-23 5 views
1

Я пытаюсь сделать внешний вызов AJAX для API в каждом цикле Jquery.Javascript scope/hoisting OR обещает/откладывает?

Вот код, который у меня есть.

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" 
}); 

GetStylesInfo() возвращает что-то похожее на это. Массив объектов с информацией о модели автомобиля.

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}]; 

Я пытаюсь петлю через sampleReturnedData и использовать каждый идентификатор в качестве параметра в другой AJAX вызова с помощью функции getNavigationInfo().

Я хочу просмотреть результаты и сделать чек. Если это правда, я хочу, чтобы весь объект попал в массив держателей.

Проблема заключается в том, что console.log (владелец) вне функции возвращает пустой массив. Консоль.log (держатель) внутри оператора if работает правильно.

Я не уверен, что это проблема с объемом/подъемом или проблема с тем, как я использую отложенные данные?

Я прочитал this вопрос и многие понравятся. Они предлагают использовать либо

async:false 

Или переписать код лучше. Я много раз пытался использовать консольный отладчик. Я не хочу устанавливать значение false. Я просто не знаю, что именно происходит.

Я также прочитал о подъеме через статью this.

Я считаю, что это связано с отсрочками, но у меня недостаточно знаний JS, чтобы понять это.

Спасибо!

ответ

3

Я не уверен, что это проблема с объемом/подъемом или проблема с тем, как я использую отложенные данные?

На самом деле, это как:

  • holder объявляется только в функции обратного вызова (в качестве локальной переменной), так что undefined вне функции.
  • И console.log выполняется до того, как асинхронная функция обратного вызова заполнит массив значениями, поэтому даже если holder был в области видимости, он все равно был бы пустым. Смотрите также Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference

Так что вы должны сделать, это на самом деле переписать код, чтобы использовать обещания правильно :-)

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

Кроме того, я предполагаю, что 'styles' должен быть вложенным объектом внутри 'data' – wahwahwah

Смежные вопросы