Подтвердить что ты не робот

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();
4b9b3361

Ответ 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