Магистральный маршрутизатор: как дождаться готовности представлений?

В картографическом приложении, организованном с помощью Backbone, в основном представлении отображаются пути на карте. Этому представлению нужны данные, которые оно извлекает с сервера при первой загрузке, что занимает время (~ 500 мс).

Каждый путь имеет уникальный URL-адрес, настроенный с помощью route/navigate.

Когда пользователь щелкает внешнюю ссылку этого URL-адреса и попадает в приложение, представление карты не может сразу отобразить путь; сначала нужно получить данные.

Я настроил довольно сложный/запутанный процесс, чтобы сделать это (описано ниже), но мне интересно, есть ли лучший/канонический способ сделать это?


Вот мое решение до сих пор:

  1. In general
    • there is a global "View" called "dispatch" that is not really a view, but is used to store the state of the various other views
    • когда готово, представление карты запускает событие для отправки, так что оно знает, что карта готова («mapIsReady»)
  2. Upon loading a new url
    • on a new url, the route object updates the model immediately, and then triggers an event to dispatch, saying in essence "update the path when possible"
    • после получения этого сообщения диспетчер отслеживает состояние представления карты (которое он хранит сам) с помощью setTimeout
    • когда представление карты готово, диспетчер запускает событие «обновить» в модели, которое указывает каждому представлению показать его.

Преимущества

  • оно работает!
  • представления не вызывают методы друг друга напрямую, все делается через события

Ограничения

  • диспетчерский "вид" на самом деле вообще не вид
  • цепочка событий может быть немного сложной для отслеживания... и для отладки в будущем
  • setTimeout не кажется правильным

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

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


person Bambax    schedule 21.03.2014    source источник
comment
Если вы поместите какой-то код, это будет более понятно.   -  person Nakul91    schedule 21.03.2014
comment
Ваше представление карты извлекает данные откуда-то в порядке? это от третьего лица? вы вызываете этот метод. (может быть REST) ​​через модель... вы можете использовать для нее функции обратного вызова успеха и ошибки. Поэтому, когда выборка данных карты возвращает успех, вы можете обработать после этого успешный обратный вызов. или если ошибка обработает ее при ошибке, перезвоните   -  person Nakul91    schedule 21.03.2014


Ответы (2)


Неплохо создать отдельный объект для управления сложной логикой в ​​нескольких представлениях. Но не обязательно делать это view. Вы можете использовать простой объект JS в качестве своего рода контроллера/посредника.

Также я думаю, что в этом случае лучше использовать промисы (например, $.Deferred() ). Они значительно упрощают управление асинхронной логикой в ​​приложении, например, вы можете сделать что-то вроде:

$.when(prepareMapView, loadPathData).done(showPathToView);
person Dmytro Yarmak    schedule 21.03.2014
comment
Использование обещаний не было бы плохой идеей, за исключением того, что mapView нужно подготовить только один раз, в то время как он может показывать много путей (один, прочитанный из URL-адреса, а затем другие пути, следующие за пользователем). Так что да, для первого пути из URL-адреса мы могли бы связать его после подготовки карты, но в этом конкретном случае нам нужно было бы отфильтровать общее событие синхронизации, которое сообщает представлению карты выполнить рендеринг. Использование флагов, хотя и несколько неэлегантное, ИМХО является более общим подходом. - person Bambax; 22.03.2014
comment
Ограничение, заключающееся в том, что mapView нужно подготовить только один раз, легко решить с помощью обещания. Вы должны просто кэшировать созданное обещание и вернуть его из метода prepareMapView. Итак, в первый раз вы создаете обещание, сохраняете и возвращаете его и выполняете асинхронную подготовку, а в следующий раз вы просто возвращаете сохраненное обещание (решенное или нет). - person Dmytro Yarmak; 22.03.2014

Yo может использовать так:

this.yourMapModel.fetch({
  success: function(model, response, options){
      //"your code after successful return from url"
  },error:function(model, response, options){
       //"your code after error"
});
person Nakul91    schedule 21.03.2014