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

Backbone.js - получение дополнительных данных вместе с запросом

У меня есть коллекция, которая содержит некоторых пользователей. Некоторая информация, которая необходима, - это сколько всего есть, сколько страниц и т.д. Как передать эти данные клиенту? Или они должны поступать с отдельного представления, и в этом случае мне понадобится более одного вызова ajax? Я хотел бы иметь коллекцию fetch(), а также получить некоторые из этих "метаданных". Какой хороший способ справиться с этим?

4b9b3361

Ответ 1

Как правило, вам нужно обработать это в методе анализа класса коллекции. Его ответственность - принять ответ и вернуть массив атрибутов модели. Тем не менее, вы могли бы сделать больше, если хотите, если вы не возражаете против метода анализа, который несет дополнительную ответственность.

UserList = Backbone.Collection.extend({

    model: User,

    url: '/users',

    parse: function(data) {
        if (!data) {
            this.registered_users = 0;
            return [];
        }
        this.registered_users = data.registered_users;
        var users = _(data.users).map(
            function(user_data) {
                var user = {};
                user['name'] = user_data.name;
                return user;
            }
        );
        return users;
    }
});

Итак, в приведенном выше тривиальном примере предположим, что сервер возвращает ответ, который содержит количество зарегистрированных пользователей и массив атрибутов пользователя. Вы оба разобрали бы и вернули бы пользовательские атрибуты, и вы выберете зарегистрированный счетчик пользователей и просто установите его как переменную на модели.
Метод parse будет вызван как часть выборки. Поэтому нет необходимости изменять выборку, просто используйте встроенный метод hook, который у вас есть.

Пуристы скажут, что вы даете метод parse второстепенную ответственность, которая может удивить некоторых людей (например, что-то возвратить и модифицировать состояние модели). Однако, я думаю, это нормально.

Ответ 2

Один из способов сделать это - переопределить метод Collection::fetch(), чтобы он анализировал эти метаданные из ответа. Вы могли бы вернуть ваш backend ответ следующим образом:

{
    "collection": [
        { ... model 1 ... },
        { ... model 2 ... },
        ...
    ],
    "total_rows": 98765,
    "pages":      43
}

В вашем методе fetch, который переопределяет исходный метод Backbone.Collection::fetch(), вы можете обрабатывать каждое свойство объекта отдельно. Здесь вы можете сделать переопределение с помощью слегка измененного метода fetch:

_.extend(Backbone.Collection.prototype, {
  fetch : function(options) {
    options || (options = {});
    var collection = this;
    var success = options.success;
    options.success = function(resp) {
      // Capture metadata
      if (resp.total_rows) collection.total_rows = resp.total_rows;
      if (resp.pages)      collection.pages      = resp.pages;

      // Capture actual model data
      collection[options.add ? 'add' : 'refresh'](
        collection.parse(resp.collection), options);

      // Call success callback if necessary
      if (success) success(collection, resp);
    };
    options.error = wrapError(options.error, collection, options);
    (this.sync || Backbone.sync).call(this, 'read', this, options);
    return this;
});

Обратите внимание, что этот подход с использованием _.extend будет влиять на все ваши классы, которые расширяют Backbone.Collection.

Таким образом, вам не нужно делать 2 отдельных вызова на бэкэнд.

Ответ 3

Я бы загрузил информацию в pagecreation. Запишите информацию в html-документ, когда сервер создает сайт. Как будто вам вообще не нужно иметь вызов ajax. Я делаю это со всей коллекцией в ordner, чтобы не загружать первую страницу, а затем ждать, пока вызов ajax вернет необходимую информацию.

Пример кода с Python:

Линия 64: https://github.com/ichbinadrian/maps/blob/master/python/main.py < - from here

Строка 43: https://github.com/ichbinadrian/maps/blob/master/templates/index.html < - здесь