2014-11-04 48 views
0

我试图用更现代的风格重写http://m.amsterdamfoodie.nl的代码。基本上单页Angular应用程序下载一组餐馆的位置,并将它们放置在地图上。如果用户是阿姆斯特丹地区,那么也会添加用户的位置,以及到地点的距离。非必要的角度承诺

目前我管理异步退货使用了很多if (relevant object from other async call exists) then do next step。我想更多地使用承诺会更好。

,那么流程控制应该是:

  • 开始AJAX数据下载和Geolocation呼叫
  • 如果地理位置返回第一,商店COORDS供以后
  • 一旦AJAX数据下载
    • 如果地理位置可用
      • 计算距离各餐厅,并通过控制立即呈现代码
    • 否则将控制权交给渲染代码
  • 如果地理位置解析后,计算距离和重新渲染

我在互联网上发现的模式假设所有异步调用都必须在继续之前成功返回,而我的地理位置调用可能会失败(或返回距离阿姆斯特丹较远的位置),那没问题。在这种情况下我可以使用一个技巧,还是有条件的声明真的是要走的路?

+0

你的承诺仍然可以'成功resolve'即使数据是“负“或不存在 - 将此视为成功的结果。在'try/catch'块中处理'catch'类似于'catch',并处理致命的异常。 – 2014-11-04 08:01:08

+0

如何查看餐厅数据后是否解决了地理承诺问题。如果它没有解决,我不会等待它(因为结果可能是该人不在阿姆斯特丹)。 – 2014-11-05 07:36:22

+0

也许我错过了一些东西,但无论您是获取了数据还是得到了否定结果,您都可以解决它。这将是您下一步的输入。 – 2014-11-05 07:39:33

回答

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,但是当所有的承诺都是解决(履行或拒绝),而不是只解决如果所有的承诺都是履行。 Angular的$ 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 
    });