0

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

Во время рендеринга представления я хочу вызвать функцию внутри модели, которая заставляет серверный вызов извлекать некоторые данные только один раз.

Поскольку эти представления являются экземплярами одного и того же представления, все они запускают функцию внутри модели. Следовательно, создание множественного вызова сервера.
Любая идея, как я могу вызвать эту функцию внутри модели только один раз.

+1

Почему вы не заманишь модели вне поля зрения? Если вы не хотите, чтобы каждый экземпляр экземпляра выполнял какой-либо код, нет необходимости иметь этот вызов внутри представления? –

+0

только его часть просмотра ... но я хочу, чтобы ее вызывали только один раз ... и использовали во всех экземплярах представления. –

+0

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

ответ

1

Предполагая, что вы вызываете fetch на Модели. Этот вызов вернет запрос (фактически объект jqXHR). Таким образом, модель, которая может быть очень полезна:

fetchOnce: function() { 
    if (!this.fetchRequest || this.fetchRequest.readyState == 4 && this.fetchRequest.status >= 400) { 
     this.fetchRequest = this.fetch.apply(this, arguments); 
    } 
    return this.fetchRequest; 
}, 

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

Поскольку объект jqXHR является Deferred Promise объекта, в любое время fetchOnce называется, всегда можно добавить обратные вызовы (например, deferred.done):

model.fetchOnce().done(function() { console.log('model fetched!'); }); 
+0

, по-видимому, является одним из решений ... .thanks ... смотрел, есть ли у позвоночника встроенные возможности, подобные этому. –

+1

ничего плохого – mikeapr4

0

Расширение mikeapr4's answer, я сделал простую модель, которая переопределяет функцию fetch только выборка один раз (необязательно каждые Х часов).

Используется jQuery's Deferred .state() function, чтобы определить, ожидает ли запрос или завершен его запрос.

Отметьте, что я использовал MomentJS, чтобы рассчитать разницу во времени, но это может быть легко достигнуто с родными датами JavaScript.

var FetchOnceModel = Backbone.Model.extend({ 
    fetchDelay: 8, // hours before forcing another fetch, 
    /** 
    * False if the promise is pending, or the last fetch was within the delay. 
    * Force a new fetch if the lang has changed since the last fetch. 
    * @return {Boolean} fetch is needed 
    */ 
    isFetchDue: function() { 
     var lastFetch = this.lastFetch, 
      promise = this.promise, 
      // use the jQuery deferred `state` function 
      isPending = promise && promise.state() === "pending"; 

     return !isPending && !lastFetch || // not fetched yet? 
      (this.fetchDelay && moment().diff(lastFetch, 'hours') > this.fetchDelay); // is delay passed? 
    }, 

    fetch: function() { 
     if (this.isFetchDue()) { 
      this.promise = this.fetch({ 
       context: this, 
       success: this._onSync, 
       error: this._onError 
      }); 
     } 
     return this.promise; 
    }, 

    _onSync: function() { 
     this.lastFetch = moment(); 
     this.onSync.apply(this, arguments); 
    }, 
    _onError: function() { 
     this.lastFetch = null; 
     this.onError.apply(this, arguments); 
    }, 

    // left to override by the child model 
    onError: _.noop, 
    onSync: _.noop 
}); 

Тогда это прозрачно для зрения и может назвать fetch любое количество раз он хочет.

Простой вид, используя его:

var View = Backbone.View.extend({ 
    initialize: function() { 
     // use the model in case it has been already fetched 
     this.useModel(); 
     // then fetch anyway to ensure it's fetched 
     this.listenTo(this.model, 'sync', this.onModelSync); 
     this.model.fetch(); 
    }, 
    useModel: function() { 
     // ...use the model data, maybe render here. 
    } 
    onModelSync: function() { 
     // things that need to be done only when model sync succeeded. 
     this.useModel(); 
    } 
});