2014-11-04 3 views
0

Я пытаюсь переписать код для http://m.amsterdamfoodie.nl в более современном стиле. В основном одностраничное приложение Angular загружает множество ресторанов с местами и размещает их на карте. Если пользователь находится в районе Амстердама, тогда добавляется местоположение пользователя, равно как и расстояния до мест.Необязательные Угловые обещания

В настоящее время я управляю асинхронными возвратами, используя большое количество if (relevant object from other async call exists) then do next step. Я бы хотел больше использовать обещания, было бы лучше.

Таким образом, управление потоком должно быть:

  • Начало загрузки Аякса данных и геолокации вызов
  • если геолокация возвращает первый, магазин Coords для последующего
  • раз Аякса загрузки данных
    • если имеется местонахождение на карте
      • вычислить расстояние до каждого ресторана, и передать управление визуализацией код
    • еще пройти контроль немедленно, чтобы сделать код
  • если геолокация решает позже, вычислять расстояния и пересборку

Паттерны, которые я нахожу в Интернете, предполагают, что все асинхронные вызовы должны успешно вернуться, прежде чем продолжить, тогда как мой запрос геолокации может завершиться неудачей (или вернуть местоположение далеко от Амстердама), и все в порядке. Есть ли трюк, который я мог бы использовать в этом сценарии, или это условные утверждения, на самом деле пути?

+0

Ваше обещание еще может 'успешно resolve' даже если данные«отрицательный «или вообще не существует», рассматривают это как успешный результат. Обработайте 'reject' аналогично' catch' в блоках 'try/catch' и обрабатывайте фатальные исключения. –

+0

Как проверить, разрешено ли обещание геолокайона после того, как у меня есть данные ресторана. Если он не разрешился, я не буду ждать его (в результате может случиться так, что человек все равно не находится в Амстердаме). –

+0

Возможно, я что-то упустил, но вы можете решить, получили ли вы данные или получили отрицательный результат. Это станет вкладом в ваш следующий шаг. –

ответ

0

Каждый раз, когда вы используете .then, вы по существу создаете новое обещание, основанное на предыдущем обещании и его состоянии. Вы можете использовать это в свою пользу (и вам нужно).

Вы можете сделать что-то вдоль линий:

function getGeolocation() { 
    return $http.get('/someurl').then(
    function resolveHandler(response) { 
     // $http.X resolves with a HTTP response object. 
     // The JSON data is on its `data` attribute 
     var data = response.data; 

     // Check if the data is valid (with some other function). 
     // By this, I mean e.g. checking if it is "far from amsterdam", 
     // as you have described that as a possible error case 
     if(isValid(data)) { 
     return data; 
     } 
     else { 
     return null; 
     } 
    }, 
    function rejectHandler() { 
     // Handle the retrieval failure by explicitly returning a value 
     // from the rejection handler. Null is arbitrarily chosen here because it 
     // is a falsy value. See the last code snippet for the use of this 
     return null; 
    } 
); 
} 

function getData() { 
    return $http.get('/dataurl').then(...); 
} 

, а затем использовать $q.all на обоих обещаний, которые, в свою очередь, создает новое обещание, которое решает, как только все данные обещания решить.

Примечание: В Kris Kowal's Q, который Angular's $q service основан на, вы можете использовать allSettled метод, который делает почти то же самое, как all, но решает, когда все обещания поселились (выполнены или отклонены), а не только если все обещания выполнено. Угловая $ q не предоставляет этот метод, поэтому вы можете вместо этого работать с этим путем явного исключения неудачного запроса HTTP-запроса.

Таким образом, вы можете сделать что-то вроде:

$q.all([getData(), getGeolocation()]) 
.then(function(data, geolocation) { 
    // `data` is the value that getData() resolved with, 
    // `geolocation` is the value that getGeolocation() resolved with. 
    // Check the documentation on `$q.all` for this. 
    if(geolocation) { 
    // Yay, the geolocation data is available and valid, do something 
    } 

    // Handle the rest of the data 
}); 
0

Может быть, я что-то отсутствует ...но так как у вас нет зависимостей между двумя асинхронными вызовами, я не понимаю, почему вы не можете просто следовать логике вы изложенную:

var geoCoordinates = null; 
var restaurants = null; 
var distances = null; 

getRestaurantData() 
    .then(function(data){ 
    restaurants = data; 
    if (geoCoordinates) { 
     distances = calculate(restaurants, geoCoordinates); 
    } 
    // set $scope variables as needed 
}); 

getGeoLocation() 
    .then(function(data){ 
    geoCoordinates = data; 
    if (restaurants){ 
     distances = calculate(restaurants, geoCoordinates) 
    } 
    // set $scope variables as needed 
    });