javascript - react - indexeddb vs localstorage
¿Cómo puedo hacer una cadena realmente larga utilizando IndexedDB sin bloquear el navegador? (2)
Estoy escribiendo una aplicación web que genera un archivo de texto potencialmente grande que el usuario descargará, y todo el procesamiento se realiza en el navegador. Hasta ahora, puedo leer un archivo de más de 1 GB en trozos pequeños, procesar cada fragmento, generar un archivo de salida grande de manera incremental y almacenar el resultado creciente en IndexedDB. Mi intento más ingenuo, que mantuvo todos los resultados en la memoria y luego los serializó en un archivo al final, causó que todos los navegadores fallaran.
Mi pregunta es doble:
¿Puedo adjuntar a una entrada en IndexedDB (ya sea una cadena o una matriz) sin leer primero todo en la memoria? En este momento, esto:
task.dbInputWriteQueue.push(output); var transaction = db.transaction("files", "readwrite"); var objectStore = transaction.objectStore("files"); var request = objectStore.get(file.id); request.onsuccess = function() { request.results += nextPartOfOutput objectStore.put(request.results); };
está causando bloqueos después de que la salida comienza a hacerse grande. Simplemente podría escribir un montón de pequeñas entradas en la base de datos, pero luego tendría que leerlas todas en la memoria más tarde de todos modos para concatenarlas. Ver la parte 2 de mi pregunta ...
¿Puedo crear una URL de objeto de datos para hacer referencia a un valor en IndexedDB sin cargar ese valor en la memoria? Para cuerdas pequeñas puedo hacer:
var url = window.URL.createObjectURL(new Blob([myString]), {type: ''text/plain''});
Pero para cuerdas grandes esto no encaja demasiado bien. De hecho, se bloquea antes de cargar la cadena. Parece que las grandes lecturas que usan
get()
de IndexedDB hacen que Chrome, al menos, se bloquee (incluso las herramientas de desarrollador se bloquean).
¿Sería más rápido si utilizara Blobs en lugar de cadenas? ¿Es esa conversión barata?
Básicamente, necesito una forma, con JavaScript, de escribir un archivo realmente grande en el disco sin cargar todo el contenido en la memoria en cualquier momento. Sé que puede darle a createObjectURL
un archivo, pero eso no funciona en mi caso ya que estoy generando un nuevo archivo a partir de uno que el usuario proporciona.
Acabo de volver a abrir el error de Chrome que presenté hace 2 años y creé otro error para el equipo de FF , relacionado con la falla del navegador al crear un blob grande. Generar archivos grandes no debería ser un problema para los navegadores.
Almacenar un Blob usará mucho menos espacio y recursos ya que ya no es necesario realizar la conversión a base64. Incluso puede almacenar objetos de "texto / plano" como manchas:
var blob = new Blob([''blob object''], {type: ''text/plain''});
var store = db.transaction([''entries''], ''readwrite'').objectStore(''entries'');
// Store the object
var req = store.put(blob, ''blob'');
req.onerror = function(e) {
console.log(e);
};
req.onsuccess = function(event) {
console.log(''Successfully stored a blob as Blob.'');
};
Puede ver más información aquí: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
Chrome ha admitido esto solo desde el verano de 2014: http://updates.html5rocks.com/2014/07/Blob-support-for-IndexedDB-landed-on-Chrome-Dev por lo que no puede usar esto en versiones anteriores de Chrome.