ExtJs. Один запрос, несколько Ext.data.Store.

Не так давно я рассказывал о библиотеке ExtJs, ей же будет посвящена сегодняшняя заметка. Эта заметка расчитана на подготовленного читателя, который уже разобрался с базовыми понятиями. Но и новичку будет полезно взглянуть на то, что предлагает эта библиотека, возможно захочется стать подготовленным =) Комментарии будут подробными.

Стоит заметить, что речь пойдет о второй версии, которая сейчас значиться Release Candidate 1 и доступна для скачивания по ссылке

Сегодня речь пойдет об Ext.data.Store. Объект удачный и используется во множестве виджетов в качестве источника данных. Обычный подход заключается в том, чтобы создать подгружающий себя объект и вызывать метод load(), для его загрузки.

//Инициализируем соединение
var rCon = new Ext.data.Connection({
    //Урл "кормящего" файла =)
    url:    '/data.php',
    //Метод
    method: 'POST',
    //Параметры, которые передадутся в запросе
    extraParams: {'act' : 'get_requests'}
});
//Само хранилище
var rDs = new Ext.data.Store({
    //Прокси с соединением, созданным выше
    proxy: new Ext.data.HttpProxy(rCon),
    //"Читатель" ответов, приходящих в формате JSON
    reader: new Ext.data.JsonReader({
        //Какое свойство читать
        root: 'requests',
        //Какое свойство отвечает за кол-во записей
        totalProperty: 'total_requests',
        //Поля записей
        fields: [
        'requests_key',
        'requests_name'
        ]
    })
});
rDs.load();

Так выглядит обычное создание и загрузка хранилища. При вызове метода load() идет асинхронных запрос к серверу, получаются данные и далее с ними делается то, что нужно. Вcё замечательно. Есть одно «но». Хранилище в силу своей универсальности используется и для ComboBox — выпадающих списков в формах. А этих самых ComboBox в одной форме может быть много. У меня, например 19 =) Таким образом, реализуя приведенную выше схему, мы получим 19 асинхронных вызовов. А это не очень хорошо.

Известно, что у браузеров есть ограничение на количество одновременных вызовов. Благодаря комментариям, мы знаем, что это 3 для FF и 2 для IE. И мы получаем сильное снижение производительности. Это если не брать в расчет проблемы с обработкой 19 вызовов, и синхронизации загрузки с отображением. Ведь если не успеют загрузиться хранилища, а мы уже начнем показывать форму, будет не очень красиво.

Продумав это всё в голове, я пришел к выводу, что надо действовать по-другому. Надо наполнить все 19 хранилищ за один запрос. Поиски на форуме не привели к нахождению решения. Хотя пару идей я получил. В рецепте, приведенном ниже будет использован метод loadData(), вместо load(). Который просто загружает уже пришедшие данные в хранилище, никуда не обращаясь. Я не буду приводить код для 19 хранилищ, приведу для двух.

//Создаем record. Пригодится для "читателя" хранилища.
dsDataRecord = new Ext.data.Record.create([
//Пишем название свойства и мапим его
//на второй элемент массива пришедших данных
{name : 'data_key', mapping : 1},
{name : 'data_name', mapping: 2}
]);
//Хранилище номер раз.
dataStore = new Ext.data.Store({
    //Читатель на этот раз "массивный" а не JSON =)
    reader: new Ext.data.ArrayReader({
        //Первый элемент массива для упорядочивания. Он уникальный.
        id: 0
        //Наш record.
    }, dsDataRecord)
});

//Создаем record. Пригодится для "читателя" хранилища.
dsDigitRecord = new Ext.data.Record.create([
//Пишем название свойства и мапим его
//на второй элемент массива пришедших данных
{name : 'digit_key', mapping : 1},
{name : 'digit_name', mapping : 2}
]);
//Хранилище номер два.
digitStore = new Ext.data.Store({
    //Читатель на этот раз "массивный" а не JSON =)
    reader: new Ext.data.ArrayReader({
        //Первый элемент массива для упорядочивания. Он уникальный.
        id: 0
        //Наш record.
    }, dsDigitRecord)
});
//AJAX-запрос на все данные
comboStoreRequest = Ext.Ajax.request({
    //Урл "кормящего файла"
    url: 'data.php',
    //В случае успешного запроса
    success: function(result){
        //Преобразуем JSON-ответ в объект
        comboStore = Ext.util.JSON.decode(result.responseText);
        //Загрузим массив данных первое хранилище
        dataStore.loadData(comboStore.data);
        //Загрузим массив данных во второе хранилище
        digitStore.loadData(comboStore.digit);
    },
    //Метод
    method: 'POST',
    //Параметры вызова
    params: {act : 'get_data'}
});

Приведенный код тоже не слишком сложен. Самое интересное, для меня, было сформировать теперь выдачу с сервера JSON-данных, чтобы их «прожевал» ArrayReader. И сделал из них массивы, приемлемые для загрузки в хранилище.

На основе документации, можно прийти к выводу, что ArrayReader ожидает данные в виде объектов вида:


[[1, key1, name1],[2, key2, name2],[3, key3, name3]]

Значит в PHP нам необходимо иметь массив, повторяющий приведенную структуру и применить к нему json_encode()

<?php
//Массив с данными
$data_array[] = array(1, "data_key1", "data_name1");
$data_array[] = array(2, "data_key2", "data_name2");
$data_array[] = array(3, "data_key3", "data_name3");
//Выводим JSON-массив
echo json_encode($array);
?>

Первый пункт выполнен. Этими данными вполне можно «накормить» один ArrayReader. А у нас их два. А ответ от сервера один. Значит надо наши массивы упаковать как свойства объекта. И обращаться к ним при загрузке в хранилище. Для этого на сервере нужен следующий PHP-код:

<?php
//Первый массив
$data_array[] = array(1, "data_key1", "data_name1");
$data_array[] = array(2, "data_key2", "data_name2");
$data_array[] = array(3, "data_key3", "data_name3");
//Второй массив
$digit_array[] = array(1, "digit_key1", "digit_name1");
$digit_array[] = array(2, "digit_key2", "digit_name2");
$digit_array[] = array(3, "digit_key3", "digit_name3");
//Собираем всё в один массив.
$data = array('data' => $data_array, 'digit' => $digit_array);
//Выводим окончательный ответ.
echo json_encode($data);
?>

Готово. Теперь мы передаем JSON-объект с двумя свойствами, которые являются массивами данных. И мы можем загрузить их в наши dataStore. Задача выполнена =)

Реклама

комментариев 7 to “ExtJs. Один запрос, несколько Ext.data.Store.”

  1. Akzhan Says:

    спасибо за интересные материалы. маленькое дополнение для красоты:

    лучше выводить так:

    < ? php //Первый массив
    $data_array[] = array(1, «data_key1», «data_name1»);
    $data_array[] = array(2, «data_key2», «data_name2»);
    $data_array[] = array(3, «data_key3», «data_name3»);

    //Второй массив $digit_array[] = array(1, «digit_key1», «digit_name1»);
    $digit_array[] = array(2, «digit_key2», «digit_name2»);
    $digit_array[] = array(3, «digit_key3», «digit_name3»);

    $obj = array(data => $data_array, digit => $digit_array);

    //Выводим окончательный ответ.
    echo json_encode($obj);
    ? >

  2. BTheMad Says:

    Да, вы правы, ваш код изящней. Исправил и запомнил =)

  3. kuth Says:

    опечатка в первом листинге. объявленная переменная rCon, далее используется как rGridCon.

  4. Eugene Schava Says:

    JFYI: Максимальное количество одновременных соединений с сервером — 3 для фаирфокса и 2 для эксплорера

  5. BTheMad Says:

    Спасибо, kuth и Eugene Schava.
    Внес изменения.
    Нет предела совершенству =)

  6. Anonymous Says:

    На основе документации, можно прийти к выводу, что ArrayReader ожидает данные в виде объектов вида:

    [[1, key1, name1],[2, key2, name2],[3, key3, name3]]
    —————-
    Не ввиде объектов , а в виде многомерного массива.
    —————-
    Публиковать не обязательно, но исправить надо.

  7. Lul Says:

    Anonymous — в js все сделано в виде объектов и даже массив является объектом, так что…

Добавить комментарий

Please log in using one of these methods to post your comment:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s


%d такие блоггеры, как: