2016-04-08 2 views
0

Я пытаюсь получить данные для нескольких Google Адресов, а затем нарисовать маркеры для каждого места на карте. Я пытаюсь использовать обещания дождаться, пока данные для каждого места не будут получены до обновления карты. Это то, что у меня есть:Как я могу использовать обещания получить данные в Google Адресах?

var service = new google.maps.places.PlacesService(map), 
    promises = [], 
    promise = '', 
    searchCallback = function(results, status) { 

     if(status == google.maps.places.PlacesServiceStatus.OK) { 

      for(var i = 0; i < results.length; i++) { 

       var place = results[i]; 

       // this works 
       console.log(place); 

       // resolve the promise 
       promise.resolve(place); 
      } 
     } 
    } 

$('li').each(function(index) { 

    promise = $.Deferred(), 

    var lng = $(this).attr('data-longitude'), 
     lat = $(this).attr('data-latitude'), 
     name = $(this).text(), 
     latLng = new google.maps.LatLng(lat, lng), 
     request = { 
      location: latLng, 
      radius: '500', 
      query: name 
     }; 

    // push promise into array 
    promises.push(promise); 

    // get data about place 
    service.textSearch(request, searchCallback); 
} 

// when all promises are complete 
$.when.apply($, promises).then(function(data) { 
    console.log(data); 
}); 

Мой PlacesService работает нормально. Я могу console.log(place), и я вижу объект, возвращенный Google, но когда я пробую console.log(data) в своем обратном вызове $.when, data возвращает undefined. Казалось бы, мои обещания не работают должным образом. Что мне не хватает?

ответ

0

Как написано с promise в качестве внешнего вар:

  • может только когда-либо быть максимум один Deferred назначен promise.
  • по завершении цикла $('li').each(), который отложен будет последним один назначенный в пределах цикла.
  • первый service.textSearch() для успешного возвращения результатов приведет к тому, что последнее обещание будет разрешено.
  • последующие успехи попытаются решить одно и то же обещание, но не смогут этого сделать, потому что обещание может быть разрешено только один раз.

Так что если массив promises будет содержать все отложенные отсрочки, будет разрешен только последний. Все остальные Derferreds останутся «ожидающими», и $.when.apply($, promises) никогда не разрешит.

Рекомендуемая стратегия для этого типа задачи:

  • в promisify на самом низком уровне.
  • для обработки данных на самом высоком уровне.

Для обработки ошибок есть выбор дизайна. Вы можете:

  • позволяет любому лицу ошибки асинхронной сорвать весь edeavour или
  • оправиться от индивидуальных асинхронных ошибок при обращении с ними и инъекционным значением по умолчанию.

В этом случае второй вариант представляется наиболее подходящим.

var service = new google.maps.places.PlacesService(map); 

// Promisify service.textSearch() as service.textSearchAsync() 
// (lowest level) 
service.textSearchAsync = function(options) { 
    return $.Deferred(function(dfrd) { 
     service.textSearch(options, function(results, status) { 
      if(status == google.maps.places.PlacesServiceStatus.OK) { 
       promise.resolve(results); 
      } else { 
       promise.reject(new Error(status)); 
      } 
     }); 
    }).promise(); 
}; 

// Map the 'li' elements to an array of promises, exploiting the low level utility. 
// (intermediate level) 
var promises = $('li').map(function(index) { 
    return service.textSearchAsync({ 
     location: new google.maps.LatLng($(this).data('latitude'), $(this).data('longitude')), 
     radius: '500', 
     query: $(this).text() 
    }).then(null, function(error) { 
     console.error(error); 
     return $.when([]); // error recovery (deliver an empty array) such that any individual failure of `service.textSearch()` doesn't scupper the whole endeavour. 
    }); 
}).get();// .get() is necessary to remove the jQuery wrapper returned by $('li').map() 

// Aggregate the promises then handle the data gathered 
// (highest level) 
$.when.apply($, promises).then(function() { 
    console.log(arguments); // jQuery.when() delivers data 'spread' into the arguments of its .then() callback 
    var i, j, results, place; 
    for(i=0; i<arguments.length; i++) { 
     results = arguments[i]; 
     for(j=0; j<results.length; j++) { 
      place = results[j]; 
      console.log(place); 
      // now plot `place` as a marker on the map. 
     } 
    } 
}); 
Смежные вопросы