Модельные отношения Backbone.js: ускорение производительности - PullRequest
2 голосов
/ 20 октября 2011

У меня есть три связанные модели: Сегменты каждая имеет две GeoPoints , с ассоциациями, сохраненными как GeoPointOnSegments . На стороне сервера это простой код Rails с отношением has_many: through. На стороне клиента ниже приведен код Backbone, который я написал. (Примечание: я допускаю создание данных на стороне клиента, а затем пакетную загрузку; поэтому существует некоторая логика для работы с локальными и серверными идентификаторами.)

Проблема, которую я нахожу, состоит в том, что этот код очень медленный, когда у меня сотни моделей. В частности это следующая строка в geo_point.coffee:

masterRouter.geo_point_on_segments.select ...

Это делает фильтр для каждой модели GeoPointOnEntry, чтобы найти, какие из них связаны с данной GeoPoint. (Обратите внимание, что к GeoPoint может быть подключено несколько сегментов.) Есть предложения по улучшению производительности?

У меня были идеи:

  • Используйте функциональные возможности, предоставляемые https://github.com/PaulUithol/Backbone-relational, предполагая, что есть что предложить
  • На стороне сервера создайте вложенный JSON, возможно, с некоторой избыточностью.
  • Создание своего рода индекса на стороне клиента с помощью хэша JavaScript.

Есть еще идеи, лучше?

geo_point.coffee

class App.Models.GeoPoint extends Backbone.Model
  name: 'geo_point'
  getGeoPointOnSegments: ->
    masterRouter.geo_point_on_segments.select (gpos) =>
      if @isNew()
        return gpos.get('geo_point_cid') == @cid
      else 
        return gpos.get('geo_point_id') == @id
    , this
  getSegments: ->
    _.compact _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getSegment() unless gpos.get('markedForDelete')
  getConnectedGeoPoints: ->
    _.compact _.flatten _.map @getSegments(), (s) =>
      s.getGeoPoints() unless s.get('markedForDelete')

geo_point_on_segment.coffee

class App.Models.GeoPointOnSegment extends Backbone.Model
  name: 'geo_point_on_segment'
  getGeoPoint: ->
    if local = masterRouter.geo_points.getByCid(@get 'geo_point_cid')
      return local
    else if server = masterRouter.geo_points.get(@get 'geo_point_id')
      return server
  getSegment: ->
    if local = masterRouter.segments.getByCid(@get 'segment_cid')
      return local
    else if server = masterRouter.segments.get(@get 'segment_id')
      return server

segment.coffee

class App.Models.Segment extends Backbone.Model
  name: 'segment'
  getGeoPointOnSegments: ->
    _.compact masterRouter.geo_point_on_segments.select (gpos) =>
      if gpos.isNew()
        return gpos.get('segment_cid') == @cid
      else if gpos.get('markedForDelete')
        return null
      else
        return gpos.get('segment_id') == @id
    , this
  getGeoPoints: ->
    _.map @getGeoPointOnSegments(), (gpos) =>
      gpos.getGeoPoint() unless gpos.get('markedForDelete')

1 Ответ

0 голосов
/ 21 октября 2011

Я думаю, что лучше не иметь модель отношения, GeoPointOnSegment, в Backbone.

Структура, которую я хотел бы работать:

  • каждая точка имеетколлекция с сегментами, к которым он принадлежит
  • каждый сегмент имеет коллекцию / массив с точками

Это легко сделать, если при создании экземпляра данных из JSON вы что-то делаетенапример:

  • инициализация всех точек
  • инициализация всех сегментов
  • для каждого GeoPointOnSegment, добавление точки в коллекцию сегмента и сегмента в коллекцию точек,Извлечение точки и коллекции сегмента происходит быстро, так как она выполняется по id (и индексируется с помощью Backbone).

Кроме того, при создании новых сегментов необходимо поддерживать эти ассоциации.

Это индекс на стороне клиента, но интегрированный в модели.

...