Just a quick question about saving an apps state using local storage. I'm about to start work on an iOS web app and I'm wondering if there may be any advantages or disadvantage to either of these models. Also, is there any major performance hit to saving every tiny change of the app state into local storage?
Number 1
Save the entire app state object as an JSON string to a single local storage key value pair.
var appstate = {
string: 'string of text',
somebool: true,
someint: 16
}
localStorage.setItem('appState', JSON.stringify(appstate));
Number 2
Save each variable of the app state to it's own key value pair in local storage.
var appstate = {
string: 'string of text',
somebool: true,
someint: 16
}
localStorage.setItem('string', appstate.string);
localStorage.setItem('bool', appstate.somebool);
localStorage.setItem('int', appstate.someint);
The only reason I would think it could be more efficient to store values separately would be if you anticipate values changing independently of each other. If they are stored separately you could refresh one set of values without touching another, and therefore have better handling of value expiration. If, for example, somebool changes frequently but the rest does not, it might be better to store it separately. Group together data with similar expiration and volatility.
Otherwise, if you just want to save the entire application state, I would think that a single string would be fine.
Consider reads vs. writes (changes). For frequent reads, it doesn't really matter because JavaScript objects are hashes with constant (O(1)) response time (see Javascript big-O property access performance). For writes, as nullability says, there is a difference. For the single-object design, frequent writes could get slower if you end up with a large number of (or large-sized) properties in the object.
Related
I have this function which parse a value received on mqtt. The value is actually a timestamp send by an arduino and is number like 1234 , 1345 etc...
var parts = msg.payload.trim().split(/[ |]+/);
var update = parts[10];
msg.payload = update;
return msg;
What i want is actually instead last value (which is update variable in my case) is to get difference between last received value and previous one.
Basically if I receive 1234 and then 1345, I want to remember 1234 and the value returned by function to be 1345 - 1234 = 111.
Thank you
If you want to store a value to compare to later you need to look at how to use context to store it.
The context is normally an in memory store for named variables, but it is backed by an API that can be used to persist the context between restarts.
I wanted to suggest an alternative approach. Node-RED has a few core nodes that are designed to work across sequences and for this purpose, they keep an internal buffer. One of these nodes is the batch node. Some use cases, like yours, can take advantage of this functionality to store values thus not requiring using context memory. The flow I share below uses a batch node configured to group two messages in a sequence, meaning it will always send downstream the current payload and the previous one. Then a join node will work on such sequence to reduce the payload to a single value, that is the difference between the timestamps. You need to open the configuration dialog for each node to fully understand how to set up those nodes to achieve the desired goal. I configured the join node to apply a fix-up expression to divide the payload by one thousand, so you get the value in seconds (instead of milliseconds).
Flow:
[{"id":"3121012f.c8a3ce","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"2ab0e0ba.9bd5f","type":"batch","z":"3121012f.c8a3ce","name":"","mode":"count","count":"2","overlap":"1","interval":10,"allowEmptySequence":false,"topics":[],"x":310,"y":280,"wires":[["342f97dd.23be08"]]},{"id":"17170419.f6b98c","type":"inject","z":"3121012f.c8a3ce","name":"","topic":"timedif","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":280,"wires":[["2ab0e0ba.9bd5f"]]},{"id":"342f97dd.23be08","type":"join","z":"3121012f.c8a3ce","name":"","mode":"reduce","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"payload-$A","reduceInit":"0","reduceInitType":"num","reduceFixup":"$A/1000","x":450,"y":280,"wires":[["e83170ce.56c08"]]},{"id":"e83170ce.56c08","type":"debug","z":"3121012f.c8a3ce","name":"Debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":600,"y":280,"wires":[]}]
I'm using a factory to create different user-Objects from data which comes from the Server. Each user-Object has a "userGroup"-property. A list of users is displayed using ng-repeat in the View. And there it is possible to change the userGroup-value from "basic" to "admin", because of the AngularJS 1 two way binding. So the original values of the Object are gone. So my question is: when we want to cancel the made changes where should the initial value {userGroup: "basic"} be stored?
I was thinking about two possible solutions:
create an additional property "initUserGroup" in the User Factory Class and store a value for each Object
use localstorage (up to 20 records must be saved at once)
Are there any best practices for such cases?
For example, you can backup whole object in a property like _backup (using angular.copy) and restore if you with to undo changes (using angular.extend). Here is an example:
$scope.editItem(item) {
item._backup = angular.copy(item);
}
$scope.undoEdit(item) {
angular.extend(item, item._backup);
//delete unused data
delete(item._backup);
}
In this case you won't need to save data outside current object.
I have a scenario on my web application and I would like suggestions on how I could better design it.
I have to steps on my application: Collection and Analysis.
When there is a collection happening, the user needs to keep informed that this collection is going on, and the same with the analysis. The system also shows the 10 last collection and analysis performed by the user.
When the user is interacting with the system, the collections and analysis in progress (and, therefore, the last collections/analysis) keep changing very frequently. So, after considering different ways of storing these informations in order to display them properly, as they are so dynamic, I chose to use HTML5's localStorage, and I am doing everything with JavaScript.
Here is how they are stored:
Collection in Progress: (set by a function called addItem that receives ITEMNAME)
Key: c_ITEMNAME_Storage
Value: c_ITEMNAME
Collection Finished or Error: (set by a function called editItem that also receives ITEMNAME and changes the value of the corresponding key)
Key: c_ITEMNAME_Storage
Value: c_Finished_ITEMNAME or c_Error_ITEMNAME
Collection in the 10 last Collections (set by a function called addItemLastCollections that receives ITEMNAME and prepares the key with the current date and time)
Key: ORDERNUMBER_c_ITEMNAME_DATE_TIME
Value: c_ITEMNAME
Note: The order number is from 0 to 9, and when each collection finishes, it receives the number 0. At the same time, the number 9 is deleted when the addItemLastCollections function is called.
For the analysis is pretty much the same, the only thing that changes is that the "c" becomes an "a".
Anyway, I guess you understood the idea, but if anything is unclear, let me know.
What I want is opinions and suggestions of other approaches, as I am considering this inefficient and impractical, even though it is working fine. I want something easily maintained. I think that sticking with localStorage is probably the best, but not this way. I am not very familiar with the use of Design Patterns in JavaScript, although I use some of them very frequently in Java. If anyone can give me a hand with that, it would be good.
EDIT:
It is a bit hard even for me to explain exactly why I feel it is inefficient. I guess the main reason is because for each case (Progress, Finished, Error, Last Collections) I have to call a method and modify the String (adding underline and more information), and for me to access any data (let's say, the name or the date) of each one of them I need to test to see which case is it and then keep using split( _ ). I know this is not very straightforward but I guess that this whole approach could be better designed. As I am working alone on this part of the software, I don't have anyone that I can discuss things with, so I thought here would be a good place to exchange ideas :)
Thanks in advance!
Not exactly sure what you are looking for. Generally I use localStorage just to store stringified versions of objects that fit my application. Rather than setting up all sorts of different keys for each variable within localStore, I just dump stringified versions of my object into one key in localStorage. That way the data is the same structure whether it comes from server as JSON or I pull it from local.
You can quickly save or retrieve deeply nested objects/arrays using JSON.stringify( object) and JSON.parse( 'string from store');
Example:
My App Object as sent from server as JSON( I realize this isn't proper quoted JSON)
var data={ foo: {bar:[1,2,3], baz:[4,5,6,7]},
foo2: {bar:[1,2,3], baz:[4,5,6,7]}
}
saveObjLocal( 'app_analysis', data);
function saveObjLocal( key, obj){
localStorage.set( key, JSON.stringify(obj)
}
function getlocalObj( key){
return JSON.parse( localStorage.get(key) );
}
var analysisObj= =getlocalObj('app_analysis');
alert( analysisObj.foo.bar[2])
Take for example a case where I have thousands of students.
So I'd have an array of objects.
students = [
{ "name":"mickey", "id","1" },
{ "name":"donald", "id","2" }
{ "name":"goofy", "id","3" }
...
];
The way I currently save this into my localstorage is:
localStorage.setItem('students', JSON.stringify(students));
And the way I retrieve this from the localstorage is:
var data = localStorage.getItem('students');
students = JSON.parse(data);
Now, whenever I make a change to a single student, I must save ALL the
students to the localStorage.
students[0].name = "newname";
localStorage.setItem('students', JSON.stringify(students));
I was wondering if it'd be better instead of keeping an array, to maybe have
thousands of variables
localStorage.setItem('student1', JSON.stringify(students[0]));
localStorage.setItem('student2', JSON.stringify(students[1]));
localStorage.setItem('student3', JSON.stringify(students[2]));
...
That way a student can get saved individually without saving the rest?
I'll potentially have many "students".. Thousands. So which way is better,
array or many variables inside the localstorage?
Note: I know I should probably be using IndexedDB, but I need to use LocalStorage for now. Thanks
For your particular case it would probably be easier to store the students in one localStorage key and using JSON parse to reconstruct your object, add to it, then stringifying it again and it would be easier than splitting it up by each student to different keys.
If you don't have so many data layers that you really need a real local database like IndexedDB, a single key and a JSON string value is probably OK for your case.
There is limitation for the size of local storage and older browsers won't support it.
It is better to store in an array for couple reasons:
Can use loops to process them
No JSON needed
Always growable
I want to execute a java script file via the mongos for inserting data to my sharding set. In addition to that I want to add a dynamic variable and the NULL value -
I would login (manually) to the shell by
mongo hostip:port/admin my_script.js
My js looks like:
var amount = 1000000;
var x=1;
var doc= '';
for (i=0; i<amount; i++)
{
doc = { a: '1', b: '2', c: 'text' , d: 'x', e: 'NULL'}
db.mycol.insert(doc);
x=x + 1
}
(Rather "x" I could just use "i")
does "d" writes the value of "x" or just the letter "x"?
does "e" writes the text "Null" or the .. let's say "database NULL"
Is the way I do that procedure correctly? (Concerning how I connect to mongos / the sharding set)
best regards
EDIT:
And very important - how can I figure out the time, the mongodb/sharding set needs to store all the data? And balanced it?
Edit 2nd:
Hi Ross,
I have a sharding set that consists of two shards (two replicasets). At the moment I'm testing and therefore I use the loop-counter as the shard key.
Is there a way to check the time within the javascript?
Update:
So measuring the time that is needed for storing the data is equivalent to the time the javascript is executed? (Or the time the mongo shell isn't accessible because of executing)
Is that assumption acceptable for measuring the query response time?
(where do I have to store the java script file?)
You dont need to keep multiple counters - as you are incrementing i on each iteration of the for loop. As you want the values and not strings the use i for the value of d and null instead of the string "NULL" - heres the cleaned up loop:
var amount = 1000000;
for (i=1; i<amount+1; i++) {
doc = { a: '1', b: '2', c: 'text' , d: i, e: null }
db.mycol.insert(doc);
}
Regarding how long it takes to store / balance your data - that depends on a few factors.
Firstly, what is your shard key? Is it a random value or is it an increasing value (like a timestamp). A random pattern for shard keys help ensure an even distribution of writes and if you know the ranges of the shard key, you could pre-split the shard to try and ensure that it stays balanced when loading data. If the shard key is increasing like a timestamp then most likely one shard will become hot and it will always be at the top end of the range and will have to split chunks and migrate the data to the other shards.
At MongoDB UK there were a couple of good presentations about sharding: Overview of sharding and Sharding best practices.
Update:
Regarding how long will it take for the shards to become balanced - this depends on the load on your machines. Balancing is a lightweight process so should be considered a background operation. Its important to note, that even with a sharded system as soon as the data is written to the mongos its accessible for querying against. So if a shard becomes imbalanced during a data load the data is still accessible - it may take time to rebalance the shard - depending on the load of the shard and the additions of new data, meaning chunks need to be split before migrating.
Update2
The inserts to mongos are synchronous, so the time it takes to run the script is the time it took to apply the inserts. There are other options about the durability of writes using getLastError essentially how long you block while the write is written. The shell calls getLastError() transparently but the default for your language of choice is to be asynchronous and not wait for a server response.
Where to store the javascript file? - Well thats up to you - its your application code. Most users will write an application in their preferred language and use the driver to call mongodb.