4

I need to store client side data temporarily. The data will be trashed on refresh or redirect. What is the best way to store the data?

using javascript by putting the data inside a variable

var data = {
    a:"longstring",
    b:"longstring",
    c:"longstring",
}

or

putting the data inside html elements (as data-attribute inside div tags)

<ul>
    <li data-duri="longstring"></li>
    <li data-duri="longstring"></li>
    <li data-duri="longstring"></li>
</ul>

The amount of data to temporarily store could get a lot because the data I need to store are image dataUri's and a user that does not refresh for the whole day could stack up maybe 500+ images with a size of 50kb-3mb. (I am unsure if that much data could crash the app because of too much memory consumption. . please correct me if I am wrong.)

What do you guys suggest is the most efficient way to keep the data?

Jo E.
  • 7,822
  • 14
  • 58
  • 94
  • What sort of data sizes are we talking about here? Do you actually have a performance issue? I doubt there is a efficiency difference, although depends on implementation of DOM by browser and the JavaScript engine implementation. If you're using Binary data as base64 strings, you might be better with an ArrayBuffer or blob type... – Adam Jan 06 '15 at 12:04
  • @adam I haven't launched the code yet. Its a filemanager application and the client has a lot of requirements. 1 of them is that the images should not be cached and should not be accessed directly from a url. but should also be fast. so i am getting dataUri's and storing them client side as a temporary cache alternative. the app could run a whole day, so if the user does not refresh or anything we could be talking 500+ images with a size of 50kb-3mb each. So I don't know what to expect as for performance issue right now. – Jo E. Jan 06 '15 at 12:08
  • 500+ images (data uri that is) with size varying between 0.5 MB thru 3 MB == ~ 750 MB assuming an average size of 1.5 MB. You would be better off not caching it client-side. `localStorage` will also not help (maxes out at 10 MB). – Abhitalks Jan 06 '15 at 12:27
  • @Deadpool; image will always be accessible through an url unless you print them directly into the html page as base62. If you use ajax to get the images for the filemanager, someone can get the images through that api. Rather think about securing your images via userAuth/Sessions. Regarding 500*3mb, yes, that will consume 1.5Gigs of RAM on your client, not something to recommend. -> go the userAuth way – japrescott Jan 06 '15 at 12:30
  • @japrescott everything is already protected by userAuth. what they want is even more protection by not allowing staff with userAuth to check the scanned images of other staff. so images I load are from a loader script with a one time use key (e.g. `if(checkCredentials()){header("Content-type:image/png");readfile($image);}` ). My problem is that, this would really be slower compared to having client side caches. But as you all pointed out, caching that much data via javascript would cause problems. – Jo E. Jan 06 '15 at 12:37
  • @Deadpool if you already have userAuth and you know which staffer is allowed to view which staffers images, then you just need to tie these systems together instead of trying to create something on the clientside – japrescott Jan 06 '15 at 12:42
  • I believe will be a lot worse, although raw image is 3MB, data-URL will be 3MB + 33% for base64 and x2 as String (JavaScript apparently uses 2 bytes per character) + actual image storage in the DOM – Adam Jan 06 '15 at 12:58
  • @Adam I think I'm convinced to not go this path. thanks for the info guys! – Jo E. Jan 06 '15 at 13:14

6 Answers6

3

I'd recommend storing in JavaScript and only updating the DOM when you actually want to display the image assuming all the image are not stored at the same time. Also note the browser will also store the image in its own memory when it is in the DOM.

Update: As comments have been added to the OP I believe you need to go back to customer requirements and design - caching 500 x 3MB images is unworkable - consider thumbnails etc? This answer only focuses on optimal client side caching if you really need to go that way...

Data URI efficiency

Data URIs use base64 which adds an overhead of around 33% representing binary data in ASCII.

Although base64 is required to update the DOM the overhead can be avoided by storing the data as binary strings and encoding and decoding using atob() and btoa() functions - as long as you drop references to the original data allowing it to be garbage collected.

var dataAsBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";

var dataAsBinary = atob(dataAsBase64);
console.log(dataAsBinary.length + " vs " + dataAsBase64.length);

// use it later
$('.foo').attr("src", "data:image/png;base64," + btoa(dataAsBinary));

String memory efficiency

How much RAM does each character in ECMAScript/JavaScript string consume? suggests they take 2 bytes per character - although this is still could be browser dependent.

This could be avoided by using ArrayBuffer for 1-to-1 byte storage.

var arrayBuffer = new Uint8Array(dataAsBinary.length );
for (i = 0; i < dataAsBinary.length; i++) {
    arrayBuffer[i] = dataAsBinary.charCodeAt(i);
}
// allow garbage collection
dataAsBase64 = undefined;

// use it later
dataAsBase64 = btoa(String.fromCharCode.apply(null, arrayBuffer));
$('.foo').attr("src", "data:image/png;base64," + btoa(dataAsBinary));

Disclaimer: Note all this add a lot of complexity and I'd only recommend such optimisation if you actually find a performance problem.

Alternative storage

Instead of using browser memory

  • local storage - limited, typically 10MB, certainly won't allow - 500 x 3MB without specific browser configuration.
  • Filesystem API - not yet widely supported, but ideal solution - can create temp files to offload to disk.
Community
  • 1
  • 1
Adam
  • 35,919
  • 9
  • 100
  • 137
2

if you really want to loose the data on a refresh, just use a javascript hash/object var storage={} and you have a key->value store. If you would like to keep the data during the duration of the user visiting the page (until he closes the browser window), you could use sessionStorage or to persist the data undefinetly (or until the user deletes it), use localStorage or webSQL

putting data into the DOM (as a data-attribute or hidden fields etc) is not a good idea as the process for javascript to go into the DOM and pull that information out is very expensive (crossing borders between the javascript- and the DOM-world (the website structure) doesn't come cheap)

japrescott
  • 4,736
  • 3
  • 25
  • 37
1

Using Javascript variable is the best way to store you temp data. You may consider to storing your data inside a DOM attribute only if the data is related to a specific DOM element.

About the performance, storing your data directly in a javascript variable will probably be faster since storing data in a DOM element would also involve javascript in addition to the DOM modifications. If the data isn't related to an existing DOM element, you'll also have to create a new element to store that value and make sure it isn't visible to the user.

The_Black_Smurf
  • 5,178
  • 14
  • 52
  • 78
  • would there be a memory problem if the amount of data stored be about 500+ image dataUris with an estimate size of 50kb-3mb? – Jo E. Jan 06 '15 at 12:21
  • I know there's some limit about the local storage (if you want to persist data between pages) but I never reached any limit regarding the global size of variable inside javascript it self. If such limit exist, it would probably be a "per browser" limitation. – The_Black_Smurf Jan 06 '15 at 12:35
1

The OP mentions a requirement for the data to be forcibly transient i.e. (if possible) unable to be saved locally on the client - at least that is how I read it.

If this type of data privacy is a firm requirement for an application, there are multiple considerations when dealing with a browser environment, I am unsure whether the images in question are to be displayed as images to the user, or where in relation to the client the source data of the images is coming from. If the data is coming into the browser over the network, you might do well (or better than the alternative, at least) to use a socket or other raw data connection rather than HTTP requests, and consider something like a "sentinel" value in the stream of bytes, to indicate boundaries of image data.

Once you have the bytes coming in, you could, I believe, (or soon will be able to) pass the data via a generator function into a typedArray via the iterator protocol, see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array

// From an iterable 
var iterable = function*(){ yield* [1,2,3]; }(); 
var uint8 = new Uint8Array(iterable); 
// Uint8Array[1, 2, 3]

And then perhaps integrate those arrays as private members of some class you use to manage their lifecycle? see:

https://www.nczonline.net/blog/2014/01/21/private-instance-members-with-weakmaps-in-javascript/

var Person = (function() {

    var privateData = {},
        privateId = 0;

    function Person(name) {
        Object.defineProperty(this, "_id", { value: privateId++ });

        privateData[this._id] = {
            name: name
        };
    }

    Person.prototype.getName = function() {
        return privateData[this._id].name;
    };

    return Person;
}());

I think you should be able to manage the size / wait problem to some extent with the generator method of creating the byte arrays as well, perhaps check for sane lengths, time passed on this iterator, etc.

A general set of ideas more than an answer, and none of which are my own authorship, but this seems to be appropriate to the question.

corse32
  • 166
  • 5
0

Why not used @Html.Hidden ?

 @Html.Hidden("hId", ViewData["name"], new { @id = "hId" })  
Dane
  • 83
  • 5
0

There are various ways to do this, depending upon your requirement:

1) We can make use of constant variables, create a file Constants.js and can be used to store data as

"KEY_NAME" : "someval"

eg: 
var data = {
    a:"longstring",
    b:"longstring",
    c:"longstring",
}
CLIENT_DATA = data;

Careful: This data will be lost if you refresh the screen, as all the variables memory is just released out.


2) Make use of cookieStore, using:
document.cookie = some val;

For reference :http://www.w3schools.com/js/tryit.asp?filename=tryjs_cookie_username Careful: Cookie store data has an expiry period also has a data storage capacity https://stackoverflow.com/a/2096803/1904479. Use: Consistent long time storage. But wont be recommended to store huge data

3) Using Local Storage:

localStorage.setItem("key","value");
localStorage.getItem("key");

Caution: This can be used to store value as key value pairs, as strings, you will not be able to store json arrays without stringify() them.
Reference:http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_webstorage_local

4) Option is to write the data into a file
Reference: Writing a json object to a text file in javascript

Community
  • 1
  • 1
Kailas
  • 7,350
  • 3
  • 47
  • 63