如何避免回调"瀑布"?

Rob*_*son 5 javascript closures titanium-mobile

我倾向于害怕为除了相对微不足道的功能之外的任何东西编写Javascript的原因之一就是我从来没有找到一个合适的方法来避免回调瀑布,当一件事真的依赖于另一件事.有没有这样的方法?

我正在开发一款Titanium应用程序,并进入这个现实世界的场景:

我有一套设施,我需要计算距离用户当前位置的距离.这需要获取用户的当前位置(仅需要发生一次),并且在环绕设施位置时,获取每个位置并计算距离.检索位置(长/纬)的API是异步的,因此"简单"方法看起来像这样(伪代码如下):

foreach facility {
  API.getCurrentLocation( function( location ) { // async, takes a callback fxn arg
    var here = location.coordinates;

    API.getFacilityLocation( function( e ) { // async, takes a callback fxn arg
      var there    = e. coordinates;
      var distance = API.calculateFrom( here, there );
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

因为这一切都在一个循环中,我每次都在计算我当前的位置 - 比我真正需要做的更多的工作.我还没有设法以这样的方式重构这个:我只获得当前位置一次,并且仍然可以将该位置用于距离计算.

鉴于支持lambdas和闭包的语言爆炸式增长,我一直认为有人必须找到一种方法来保持这些瀑布的可管理性,但我还没有找到如何组织这种解决方案的良好解释.

有什么建议或提示吗?

任何见解都会受到极大的赞赏.

Mat*_*all 4

基本策略:不要使用匿名函数进行回调,并将循环移至返回当前位置时运行的回调中。

例子:

function recieveCurrentLocation(location) { // async, takes a callback fxn arg
    var here = location.coordinates;

    // Have to define this callback in the inner scope so it can close
    // over the 'here' value
    function recieveFacilityLocation(e) {
        var there    = e. coordinates;
        var distance = API.calculateFrom( here, there );
    }

    foreach facility {
        API.getFacilityLocation(recieveFacilityLocation);
    }
}

API.getCurrentLocation(recieveCurrentLocation);
Run Code Online (Sandbox Code Playgroud)