Как избежать «водопада» обратного вызова?

Одна из причин, по которой я боюсь писать 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 );
    });
  });
}

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

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

Любые предложения или намеки?

Любое понимание будет чрезвычайно признательно.

5
задан Rob Wilkerson 15 November 2011 в 13:51
поделиться