2012-04-04 3 views
13

Я ищу лучшее решение для двух вещей:Backbone.js: Элегантный способ проверить, если данные готовы, и если набор данных пуст

  • Как я могу понять, если данные извлекаются и готовы , Я использую BasicDealList.on("reset", function(){}), чтобы понять, получены ли данные из ajax и проанализированы и готовы к использованию, но он чувствует себя грязным.

  • Если пустой JSON приходит из выборки, таких как {}, он по-прежнему показывает BasicDealList.length как 1, а это должно быть 0, таким образом, я был вынужден, чтобы проверить, если первый элемент пуст через collection.length == 1 && jQuery.isEmptyObject(BasicDealList.toJSON()[0] который очень некрасиво.

Вот код:

BasicDeal = Backbone.Model.extend();  
BasicDealCollection = Backbone.Collection.extend({ 
    model: BasicDeal, 
    url: '/some/ajax/url/', 
}); 
BasicDealList = new BasicDealCollection(); 

BasicDealList.on("reset", function(collection, response){ 
    isEmpty = collection.length == 1 && jQuery.isEmptyObject(BasicDealList.toJSON()[0]); 
    if (isEmpty){ 
    // render no deal found html 
    } 
    else{ 
    // render list of deals 
    } 
} 
BasicDealList.fetch(); 

ответ

25

Если вам не нравится слушать для reset, вы можете передать функцию обратного вызова непосредственно .fetch():

BasicDealList.fetch({ 
    success: function(collection, response){ 
     // ... 
    } 
}); 

Если позже в вашем приложение, вы хотите узнать, уже ли вы получили данные, обычно вы можете просто проверить BasicDealList.length. Если вы хотите избежать повторных запросов на коллекции, которые на самом деле пусты на сервере, вам, вероятно, придется разработать собственное решение, например. установив флаг на .fetch():

BasicDealList.fetch({ 
    success: function(collection, response){ 
     BasicDealList.fetched = true; 
     // ... 
    } 
}); 

Как для пустого выпуска данных, вы должны возвращаться [] с сервера вместо {}. Коллекция Backbone's вызывает this.add(models, ...) в пределах .reset() и .add() проверяет, является ли аргумент models массив; если это не так, он заворачивает его в одном:

models = _.isArray(models) ? models.slice() : [models]; 

Так проходя {} приведет models набор для [{}], который не то, что вы хотите. Если вы не можете управлять сервером, вы можете сделать проверку на {} в обычном методе .parse(), возвращая [], если он найден.

+0

Благодарим вас за подробное объяснение! – Hellnar

7

Нам нужно было определить, было ли отношение RelationalModel выбрано или нет. Это наше решение (в Coffeescript).

initialize: (objects, options) -> 
    @fetched = false 
    @listenTo @, 'sync', -> @fetched = true 
12

Я знаю, что на этот вопрос уже был дан ответ, но вот альтернатива.

BasicDealCollection = Backbone.Collection.extend({ 
    model: BasicDeal, 
    url: '/some/ajax/url/', 
}); 

myCollection = new BasicDealCollection() 
deferred = myCollection.fetch() 

$.when(deferred).then(function() { 
    // do stuff when we have the data. 
}); 

Главное преимущество этого в том, что мы используем функцию «когда». Функция «когда» дает нам возможность проверять несколько вызовов извлечения и делать один успех.

$.when(deferredOne, deferredTwo, deferredThree).then(function() { 
    // do stuff when we have the data. 
}); 

Кроме того, если мы храним отложенный объект в переменной, мы можем делать такие вещи. Переменная будет флагом, чтобы сообщить нам, что мы уже загрузили данные.

if (deferred.state() === "resolved") { 
    // do stuff when we have the data. 
} 

Когда мы вызываем fetch() в коллекции, он возвращает объект отложенного jQuery.Отложенный объект jQuery может находиться в трех состояниях: «ожидающий», «отклоненный» или «разрешенный», и как только мы получим данные, он установит состояние отложенного объекта для разрешения.