FrancescoN FrancescoN - 5 months ago 100
Javascript Question

LocalForage, images and Blobs

I'm a bit confused about the use of LocalForage.
I just want to save and retrieve an image from LocalForage, here is how I do.

function preload() {

localforage.setDriver(localforage.LOCALSTORAGE).then(function() {

lcl_images[0] = new Object();
lcl_images[0].key = 'lclstorage_1';
lcl_images[0].value = 'http://www.superga.com/tcnimg/S/02/S009TE0/XBS009TE0___949______.jpg';

lcl_images[1] = new Object();
lcl_images[1].key = 'lclstorage_2';
lcl_images[1].value = 'https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/2150fb35419617.56f6327b44e47.gif';

for (var i = lcl_images.length - 1; i >= 0; i--) {

var valore = lcl_images[i].value;
localforage.setItem(lcl_images[i].key, lcl_images[i].value, function() {
console.log('Saved: ' + valore);
});
}
});
}

function use_preloaded_image() {

for (var i = lcl_images.length - 1; i >= 0; i--) {

var key = lcl_images[i].key;
localforage.getItem(lcl_images[i].key, function(err, readValue) {
console.log('Read: ', readValue);
document.getElementById(key).src = readValue;
});
}
}


The point is, I don't know if it is the right method to use images: I store them as strings, localForage should use
parse
and
stringify
.
This example is working fine (when I go offline, I refresh the page, images in localstorage are vsible), but I see someone using Image objects or Blobs (I neve heard about that, and an instant search hasn't told me much about that).
other do an XHR request to download the image, then they save it.

I can think about the use of XHR request for the need of checking whether the image has been downloaded. Is this right?

Secondly: someone says that storing with blobs is better. Why?

Please help me, thanks.

EDIT (Multiple Promises)

When I retrieve images I must bind each of them to an
<img>
. But I don't know how to do it, with promises. Because when using
Promise.all()
I can't use a
for
loop (so no index to bind images src with images id).

var promises = [];

for (var i = lcl_images.length - 1; i >= 0; i--) {
promises.push(localforage.getItem(lcl_images[i].key));
}

Promise
.all(promises)
.then(function(value) {
console.log(value);
})
.catch(function(error) {
console.log(error);
});

for (var i = lcl_images.length - 1; i >= 0; i--) {
document.getElementById(lcl_images[i].key).src = value;
}



Promise
.all(promises)
.then(function(value) {
console.log(value);
document.getElementById(lcl_images[i].key).src = value;
// I can't get the index i, no way to set <img> src for id attribute
})
.catch(function(error) {
console.log(error);
});

Answer

Blobs are better because IndexedDB can optimize their storage on disk. In essence it stores them directly as file handles. (In cases where Blobs aren't supported or IDB isn't supported, LocalForage will convert to base64.)

To download an image as a Blob, the easiest way is to use a fetch polyfill or the fetch() API and use response.blob() (see MDN docs). Another way is to use XMLHttpRequest and do xhr.responseType = 'blob. Example:

fetch('http://example.com/myimage.gif').then(function (response) {
  return response.blob();
}).then(function (blob) {
  console.log("yay I have a blob", blob);
}).catch(console.log.bind(console))

Also another thing you should know is that it looks like you are making a classic Promise mistake in your code, which is to do multiple Promises within a forEach() loop. You probably would rather do Promise.all(). Please read We have a problem with promises for more details.

For working with Blobs, you can check out blob-util, which has a tutorial, or you can read the PouchDB guide to attachments. (PouchDB uses Blobs similarly to LocalForage, so the advice is similar.)