Доброго времени суток!
Дано: lodash, jQuery, ES6 без ограничений
Есть задача по рендеру html-блоков кода с переменными значениями на lodash в ячейки таблицы.
Отбросим вопрос, почему так пришлось и зачем это нужно, пусть у нас будет 100000 сферических в вакууме ячеек разных таблиц, с атрибутами:
<td data-x="%x-id%" data-x="%y-id%"></td>
Есть шаблон для lodash, который содержит в себе 100 строк html. В зависимости от входных параметров результируется
<input>
,
<textarea>
или
<select>
, все они обрамлены небольшой bootstrap-лапшой и кучей атрибутов
data-smth="smth_prop"
Работа алгоритма такая: на вход приходит внушительный массив информации о полях ввода, которые в цикле начинают рендериться с помощью lodash в html.
Как оказалось, если lodash берет шаблон из кеша браузера (каждый раз пытаясь загрузить его по ajax) рендер 400 полей происходит за
500ms-800ms -- результат приемлимый. Все к тому же происходит асинхронно, рендер происходит ровно после загрузки шаблона из кеша. Но подобная практика отвратительна -- мы посылаем столько запросов к серверу, сколько у нас полей. 10000 запросов. Да, они кешируются. Но это неправильно.
А вот если мы сохраним этот шаблон в localStorage, и lodash будет каждый раз брать его уже не из ajax-запроса, а из localStorage, то рендеринг тех же
400 полей произойдет за
2000ms!
В 3-4 раза медленнее! Ну, а добавив к этому отсутствие асинхронности, получаем фриз браузера на
2 секунды.(представили 10000 ячеек? Получили
минуту).
localStorage имеет ключ с названием url до шаблона, функция рендера перед загрузкой по ajax проверят наличие данных в localStorage по ключу, равному запрашиваемому url, например, ('template/input.tmpl'). Если там данные есть, не запускает ajax, а берет прямо оттуда. Если ключа нет - берет данные по ajax, как получил их, записывает в localStorage.
Заметил, что если уменьшить размер шаблона, то рендеринг происходит заметно быстрее. То есть, влияет на скорость количество текста для рендеринга. Если допустить, что localstorage не умеет кешироваться или просто медленный, и запрашивать его каждый раз неправильно, то я попробовал перед выполнением цикла рендера скопировать поэлементно его содержимое в просто-объект, и рендеру дать просто-объект -- результат тот же. Убираем вообще localstorage -- браузер посылает сотни ajax-запросов и быстрее парсит в разы =)
Что делать?
P.S.:
Скорость между
$('[data-x="124"][data-y="345"]').append()
и
getElementById('x124_y345').innerHTML
-- вообще не значительна
Скорость между
for (var i = orderedJSON.length - 1; i >= 0; i--) {}
и
for (var i in orderedJSON) {}
-- тем более