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();
Ответы
Ответ 1
Если вам не нравится слушать reset
, вы можете передать обратный вызов непосредственно на .fetch()
:
BasicDealList.fetch({
success: function(collection, response){
// ...
}
});
Если позже в вашем приложении вы хотите узнать, уже ли вы загрузили данные, обычно можно просто проверить BasicDealList.length
. Если вы хотите избежать повторных запросов на коллекции, которые на самом деле пусты на сервере, вам, вероятно, придется разработать собственное решение, например. установка флага на .fetch()
:
BasicDealList.fetch({
success: function(collection, response){
BasicDealList.fetched = true;
// ...
}
});
Что касается проблемы с пустыми данными, вы должны возвращать []
с сервера вместо {}
. Backbone Collection вызывает this.add(models, ...)
внутри .reset()
, а .add()
проверяет, является ли аргумент models
массивом; если это не так, оно обертывает его одним:
models = _.isArray(models) ? models.slice() : [models];
Таким образом, передача {}
приведет к тому, что models
будет установлен в [{}]
, что вам не нужно. Если вы не можете управлять сервером, вы можете выполнить проверку {}
в пользовательском методе .parse()
, возвращая []
, если он найден.
Ответ 2
Я знаю, что этот вопрос уже был дан, но вот альтернатива.
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 может находиться в трех состояниях: "ожидающий", "отклоненный" или "разрешенный", и как только у нас будут данные, он будет определять состояние отложенного объекта.
Ответ 3
Нам понадобился способ определить, было ли отношение RelationalModel выбрано или нет. Это наше решение (в Coffeescript).
initialize: (objects, options) ->
@fetched = false
@listenTo @, 'sync', -> @fetched = true