Przechowuję dużą liczbę małych obiektów w IndexedDB. Chciałbym umożliwić użytkownikowi wyeksportowanie jednego ze sklepów obiektów do pliku, który może "pobrać".Jak mogę umożliwić użytkownikom wydajne zapisywanie zawartości magazynu obiektów indeksowanych DB do pliku?
Przeczytałem this blog article. Co oznacza czytanie danych, kodowanie ich przy pomocy encodeURIComponent
i umieszczanie ich jako href
dla łącza, z którego mogą pobrać dane. Coś takiego:
var transaction = db.transaction([objectstore], "readonly");
var content = [];
var objectStore = transaction.objectStore(objectstore);
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
content.push({key:cursor.key,value:cursor.value});
cursor.continue();
}
};
transaction.oncomplete = function(event) {
var serializedData = JSON.stringify(dataToStore);
link.attr("href",'data:Application/octet-stream,'+encodeURIComponent(serializedData));
link.trigger("click");
};
To jest w porządku, z wyjątkiem sklepu obiekt będzie mieć miliony rekordów i nie czuję, że to będzie wystarczająco wydajna. Czy istnieje sposób, aby bardziej bezpośrednio umożliwić użytkownikowi zapisanie składnicy obiektów jako pliku (w sposób, który mogę ponownie zaimportować za pośrednictwem strony internetowej).
Edit Od niektórych notatek w komentarzach przepisał mi trochę o tym, jak to działa, aby uzyskać trochę więcej soku z niego. Nowy kod jest podobny do:
var transaction = db.transaction([objectstore], "readonly");
var objectStore = transaction.objectStore(objectstore);
objectStore.getAll().onsuccess = function(evt) {
var url = window.URL.createObjectURL(new Blob(evt.target.results, {'type': 'application/octet-stream'}));
link.attr('href', url);
link.trigger('click');
};
które dadzą mi wyniki jak:
- zapisów 10k, 975.87ms średni czas eksport
- 100k rekordów, 5,850.10ms czas średni eksportowej
- 1mil rekordy, 56 681,00ms średni czas eksportu:
Jak widać, milion rekordów zajmuje około minuty t. Czy istnieje lepszy sposób na robienie tego? (Próbowałem też użyć kursora zamiast .getAll()
, ale kursory są wolniejsze)
Chcę powiedzieć: "użyj localStorage dla zasobu aktualnie oglądanego (i do zapisywania/ładowania), i umieść DB w WebWorker", ale mam wrażenie, że nawet to nie wpłynęłoby zbytnio na wydajność. –
Tak, myślałem o zrobieniu ładowania i serializacji od webworkera, ale wciąż musi być serializowane przez przeglądarkę, aby wrócić; które moim zdaniem przyniosą taki sam wynik. Jeśli chodzi o lokalną pamięć masową, nie sądzę, że umieszczenie 3 milionów obiektów + jest dobrym pomysłem ... – Chad
czy spróbowałeś? wydostanie się z 3 milionów obiektów z IndexedDB powinno zająć tylko kilka sekund. Tworzenie pliku poprzez 'window.URL.createObjectURL (new Blob (content, {'type': MIME_TYPE}))' powinno być w porządku. –