Хранение упорядоченного объекта / массива в localStorage - PullRequest
2 голосов
/ 16 марта 2012

Я построил это расширение Chrome для нашего внутреннего портала.На этом портале есть форма, в которой вводится только одна текстовая область.Пользователи обычно публикуют набор строк в этой форме.Таким образом, мое расширение сохраняет эти значения при локальной отправке и отображает историю команд, которые пользователь отправил в форме в обратном хронологическом порядке.

В настоящее время я сохраняю каждую команду как значение, а текущую метку времени - как ключ вLocalStorage.Если пользователь публикует одни и те же данные дважды, они сохраняются в виде двух разных пар ключ-значениеПри каждой загрузке страницы я получаю все ключи из localStorage в массиве, сортирую массив в обратном хронологическом порядке.Затем повторите итерацию по массиву, чтобы создать еще один массив с объектами пары ключ-значение.Затем я отображаю их в узлах DOM как историю команд ввода.

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

Есть два способа сделать это.ЭТО ГДЕ НУЖНА ПОМОЩЬ.

1-й метод : Создайте один объект с ключами в качестве команды и значениями в качестве текущей метки времени.Скажем:

var command = $('textarea').val();
var storageTank = JSON.parse(localStorage["MyTank"]);
storageTank[command] = new Date().getTime();
localStorage["MyTank"] = JSON.stringify(storageTank);

Итак, мой StorageTank выглядит как

{ 
  "run": 1331916048253, 
  "stop": 1331916049963, 
  "modify":1331916086324,
  "delete": 1331916099874
  //and so on... Remember there can be as much as 1000 to 1500 of such commands,
  //some of them very large
}

Теперь мои данные хранятся в виде неупорядоченного словаря.Всякий раз, когда (в основном onload) мне нужно отображать их в (обратном) хронологическом порядке, мне нужно будет создать массив объектов, каждый из которых содержит ключ (команду) и запрос (метку времени), и отсортировать их.Например, [{"run": 1331916048253},{"stop": 1331916049963},{"modify":1331916086324},{"delete": 1331916099874}]

2-й метод : я сохраняю команды в массиве объектов, содержащих только одно свойство, и просто использую push, pop иreverse ради сохранения хронологии.Например,

var command = $('textarea').val();
var entity = {};
entity[command] = new Date().getTime();
var storageTank = JSON.parse(localStorage["MyTank"]);
storageTank.push(entity);
localStorage["MyTank"] = JSON.stringify(storageTank);

Теперь мой накопительный бак выглядит следующим образом

[
    {"run": 1331916048253},
    {"stop": 1331916049963},
    {"modify":1331916086324},
    {"delete": 1331916099874}
]

Теперь мне не нужно сортировать их каждый раз, когда я хочу отобразить или, другими словами, при каждой загрузке страницы(что происходит очень часто, так как отправка формы перенаправляется на ту же страницу).Но если перед сохранением каждой команды мне нужно будет сначала пройтись по массиву, чтобы проверить, существует ли уже та же команда, и перезаписать, если она есть, и это произойдет при отправке формы, то есть до тех пор, пока этот вопрос не будет отсортирован out, форма не будет отправлена.

Теперь какой путь будет более эффективным.

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 16 марта 2012

Для вашей схемы данных требуется тип данных, который обеспечивает как уникальность, так и порядок.Другие языки предоставляют это автоматически (упорядоченные хеши и т. Д.), Но в Javascript вам нужно выбирать между объектом, который обеспечивает уникальность, или массивом, который обеспечивает упорядочение.

Вы упомянули, что ваши объекты storageTank содержат много объектовоколо 1000-1500, так что давайте посмотрим, сколько времени потребуется, чтобы отсортировать это:

Для тестирования я создал эту функцию, которая генерирует объект, похожий на ваш, он использует underscore.js.

function build (size) {
    return _.chain(size)
            .range()
            .shuffle()
            .map(function (v) {return {'command': v};})
            .value();
}

console.log(build(10));
> [
    {'command': 4},
    {'command': 0},
    {'command': 2},
    {'command': 8},
    {'command': 5},
    {'command': 1},
    {'command': 3},
    {'command': 9},
    {'command': 6},
    {'command': 7}
]

Итак, давайте посмотрим, сколько времени потребуется для сортировки этого массива по клавише 'command':

b = build(10);
console.time('a');
b.sort(function (a, b) {return a.command - b.command});
console.timeEnd('a')

a: 0ms

Я повторил этот тест для многих значений build(size), и это результат:

size: 10,       time: 0ms
size: 20,       time: 0ms
size: 40,       time: 0ms
size: 80,       time: 0ms
size: 160,      time: 0ms
size: 160,      time: 0ms
size: 320,      time: 0ms
size: 640,      time: 0ms
size: 1280,     time: 1ms
size: 2560,     time: 1ms
size: 5120,     time: 3ms
size: 10240,    time: 5ms
size: 20480,    time: 10ms
size: 40960,    time: 28ms
size: 81920,    time: 43ms
size: 163840,   time: 228ms
size: 327680,   time: 444ms
size: 655360,   time: 997ms
size: 1310720,  time: 2330ms

Таким образом, если ваш объект не содержит более 100 тыс. Записей, время сортировки останется менее 50 мс, что незаметно для человека.Даже если ваш объект содержит столько записей, JSON.stringify станет вашим узким местом, а не сортировкой.

Это означает, что сортировка выполняется очень быстро.Используйте свой первый метод.

1 голос
/ 18 апреля 2012

Вы должны выбрать между сохранением упорядоченного списка или пар ключ-значение в javascript, нет никакого способа обойти это.Однако двигатель V8 сохраняет порядок ваших пар ключ / значение.Хотя это должно быть проверено / подтверждено обширным тестированием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...