Is there any kind of persistence framework for JavaScript and/or the Google v8 engine?
I want to store (serialize) a whole graph of objects (including, e.g., functions) and re-load it later. JSON is not sufficient, since it does not permit functions to be stored and permits only a tree-like structure (i.e. no two objects referencing the same object).
I need to be able to do that generically (i.e. without knowing the JavaScript code at the time at which I write my program embedding v8), since I want the user of my program to be able to customize it with JavaScript, but I need to store the state of my program (including the state of the customization) and re-load it later. Hence I need to store the state of the JavaScript engine.
Edit:
Example:
Suppose we have the following code:
var obj = { a: 4, b: function (x) { return x + this.a; } }
// ...
if ( ... ) { obj.a = 5; }
// ...
if ( ... ) { var c = 1; obj.b = function (x) { return x + this.a + c; } }
// ...
// now I want to serialize obj
Then is it (without any meta-information about the logic of the program) possible to serialize obj and later deserialize it such that obj.b (2) delivers the same result after deserialization as it did before serialization?
Second Edit: Note the closure.
Unfortunately, what you're trying to do is not currently possible in Javascript. The reason is that closures are not just objects, they're objects bound to an execution context.
Getting past the "this can't be done in javascript" issue and moving into the "what if wrote a patch for V8 to allow this" phase of the answer, this is conceptually difficult. Essentially, for every closure you'd serialize, you would have to serialize the Context object that the closure exists in. It'd be nice to be able to just serialize the HandleScope, but the nature of closures is that you can't reach inside them.
Okay, so let's say you've written a function that can serialize the Context that the closure exists in, and you can even deserialize it. What do you do with it?
The answer to that is 'not much'. Javascript can only be executed in a single context at a time. The closure that you've deserialized doesn't exists in the context that you're trying to pull it back into. You can't really pass data between contexts, and if your function has data bound to free variables, do you use the ones that exist in the deserializer-invoking context, or do you overwrite it with the deserialized context? Conceptually, this is a nightmare.
Ecmascript Harmony had considered giving us nearly-first-class continuations, but it's been pushed form the discussion which I rant about here, but this isn't going to happen any time soon.
HTML5 local storage allows persistence at client level through javascript.
I'm not sure if it will fit your needings, as to being able to store a function you'll need to somewhat give it some markup that allows you to deserialize it when retrieving it from storage (or maybe just store it as plain text and try to eval it on retrieval)
http://diveintohtml5.info/storage.html
I don't think persisting functions is a good practice. I can suggest you the below approach. Turn your JSON data to lets say some class like "MyData". You can find two functions fromJSON, toJSON which will do the magic you want.
var MyData = function(props){
this.temp = "a";
this.getTemp = function(){
return this.temp;
}
this.fromJSON = function(props){
if(props){
this.temp = props.temp;
}
}
this.toJSON = function(){
var props = {};
props.temp = this.temp;
return props;
}
this.fromJSON(props);
}
var obj = new MyData({"temp" : "b"});
var state = obj.toJSON();
// persist state about the object as JSON string
LOCALSTORAGE.put(state); // You can write some HTML5 local storage stuff to persist
var persistedState = LOCALSTORAGE.get(); // You can use the above HTML5 local storage stuff to read the persisted stuff
var newBornObj = new MyData(persistedState);
Related
I'm building a WebGL game and I've come so far that I've started to investigate performance bottlenecks. I can see there are a lot of small dips in FPS when there are GC going on. Hence, I created a small memory pool handler. I still see a lot of GC after I've started to use it and I might suspect that I've got something wrong.
My memory pool code looks like this:
function Memory(Class) {
this.Class = Class;
this.pool = [];
Memory.prototype.size = function() {
return this.pool.length;
};
Memory.prototype.allocate = function() {
if (this.pool.length === 0) {
var x = new this.Class();
if(typeof(x) == "object") {
x.size = 0;
x.push = function(v) { this[this.size++] = v; };
x.pop = function() { return this[--this.size]; };
}
return x;
} else {
return this.pool.pop();
}
};
Memory.prototype.free = function(object) {
if(typeof(object) == "object") {
object.size = 0;
}
this.pool.push(object);
};
Memory.prototype.gc = function() {
this.pool = [];
};
}
I then use this class like this:
game.mInt = new Memory(Number);
game.mArray = new Memory(Array); // this will have a new push() and size property.
// Allocate an number
var x = game.mInt.allocate();
<do something with it, for loop etc>
// Free variable and push into mInt pool to be reused.
game.mInt.free(x);
My memory handling for an array is based on using myArray.size instead of length, which keeps track of the actual current array size in an overdimensioned array (that has been reused).
So to my actual question:
Using this approach to avoid GC and keep memory during play-time. Will my variables I declare with "var" inside functions still be GC even though they are returned as new Class() from my Memory function?
Example:
var x = game.mInt.allocate();
for(x = 0; x < 100; x++) {
...
}
x = game.mInt.free(x);
Will this still cause memory garbage collection of the "var" due to some memcopy behind the scenes? (which would make my memory handler useless)
Is my approach good/meaningful in my case with a game that I'm trying to get high FPS in?
So you let JS instantiate a new Object
var x = new this.Class();
then add anonymous methods to this object and therefore make it a one of a kind
x.push = function...
x.pop = function...
so that now every place you're using this object is harder to optimize by the JS engine, because they have now distinct interfaces/hidden classes (equal ain't identical)
Additionally, every place you use these objects, will have to implement additional typecasts, to convert the Number Object back into a primitive, and typecasts ain't for free either. Like, in every iteration of a loop? maybe even multiple times?
And all this overhead just to store a 64bit float?
game.mInt = new Memory(Number);
And since you cannot change the internal State and therefore the value of a Number object, these values are basically static, like their primitive counterpart.
TL;DR:
Don't pool native types, especially not primitives. These days, JS is pretty good at optimizing the code if it doesn't have to deal with surprizes. Surprizes like distinct objects with distinct interfaces that first have to be cast to a primitive value, before they can be used.
Array resizing ain't for free either. Although JS optimizes this and usually pre-allocates more memory than the Array may need, you may still hit that limit, and therefore enforce the engine to allocate new memory, move all the values to that new memory and free the old one.
I usually use Linked lists for pools.
Don't try to pool everything. Think about wich objects can really be reused, and wich you are bending to fit them into this narrative of "reusability".
I'd say: If you have to do as little as adding a single new property to an object (after it has been constructed), and therefore you'd need to delete this property for clean up, this object should not be pooled.
Hidden Classes: When talking about optimizations in JS you should know this topic at least at a very basic level
summary:
don't add new properties after an object has been constructed.
and to extend this first point, no deletes!
the order in wich you add properties matters
changing the value of a property (even its type) doesn't matter! Except when we talk about properties that contain functions (aka. methods). The optimizer may be a bit picky here, when we're talking about functions attached to objects, so avoid it.
And last but not least: Distinct between optimized and "dictionary" objects. First in your concepts, then in your code.
There's no benefit in trying to fit everything into a pattern with static interfaces (this is JS, not Java). But static types make the life easier for the optimizer. So compose the two.
I have a program that is incrementing requests on a session cookie and printing them out to the console. Initially, I was trying to figure out how I could save this data. After logging in a couple places, I realized that the data was being saved/changed despite me having a seperate variable to hold what I thought was a temporary version of the req member object.
This is the code that made me realize that the actual object was being changes when I incremented the variable I assigned it to:
recordRequest(req) {
const { ip } = req.info;
const { requestsPerSecond } = req.session;
if (req.originalUrl.split('/').filter(Boolean)[0] == 'www.example.com') {
requestsPerSecond[ip] = requestsPerSecond[ip] + 1 || 1;
}
console.log(req.session.requestsPerSecond);
}
I can't seem to find in the docs here or on Mozilla whether or not this is intended behavior, whether or not this is a result of my use of const (where you can mutate member variables), or there is some kind of weird bug going on. I also had trouble reproducing this example on a smaller scale, but I verified that nothing going in or going out of the function is affecting this chunk of code.
It's not breaking my code or anything (it's actually making my life easier) but I want to understand why this is happening!
I would default to object destructuring working essentially the same as normal assignments. Consider:
const req = {session: {requestsPerSecond: {"0.0.0.0": "foo"}}};
const requestsPerSecond = req.session.requestsPerSecond;
// updates to `requestsPerSecond` will also update `req`.
I'm not sure you can use destructuring to break the assignment, so you will have to use normal tactics:
const requestsPerSecond = Object.assign({}, req.session.requestsPerSecond);
From MDN:
The destructuring assignment syntax is a JavaScript expression that makes it possible to extract data from arrays or objects into distinct variables.
If this data happens to be an object reference, this object reference will be copied into the new variable, or in your case constant.
Minimal example:
const orig = {
foo: {
bar: 1
}
}
const { foo } = orig;
console.log(foo.bar); // 1
console.log(orig.foo.bar); // 1
foo.bar++;
console.log(foo.bar); // 2
console.log(orig.foo.bar); // 2
I would like to set a localStorage item as a function, but when I do it gets saved as a string.
localStorage.getData = function (key="def") {
let data = null;
if (this[key] && !_this.isDataAvailableInList(this[key])) {
data = this[key].data;
}
return data;
};
The above function get stored as string and not function.
Note: Kindly do not provide alternatives or other suggestions, I am well aware of alternatives and am curious to know how this works. I have not provided the entire context so lets just assume I am in need of setting a localStorage item as a function
Unfortunately local storage is only about strings. Even arrays or other data are always converted to strings.
For most dead data without cycles you can use of course JSON.stringify and JSON.parse, but in other cases or for code or other Javascript entities unsupported by JSON (like Infinity or undefined) you need to serialize and deserialize yourself.
Javascript provides eval, so you can store the function f converting it first to a string with f+"" and get back the function with eval(s).
This won't work with closures however and moreover you cannot even know if a function is indeed a closure or not in Javascript (so you cannot even raise an error if the impossible operation of serializing a closure is attempted).
Convert the function into a string via .toString(). When you read it, convert it back to a function via new Function(myString).
Example:
No pamameters:
(new Function('var a = 0; return a + 1;'))() === 1
With parameters:
(new Function(['param0'],'var a = param0; return a + 1;'))(100) === 101
Note: The scope of the original function will be lost.
I'm looking for patterns which have been found acceptable when working with instances of js objects on the same page. (If there is a thread already covering this, a link will be appreciated.)
The issue is one of reference. After an object/feature is instantiated, it has to be referenced at some point later.
I've seen jQuery people store a reference to the object on the target DOM element using data(). However, I'm interested in a framework agnostic option if possible.
This could be accomplished if there was a clean, viable way to generate an unique id for a DOM element. Alas, I have not found one yet.
So my question is: What is the best way to store reference to an object, via a DOM element, so that you can reference it at a future arbitrary time?
Hopefully this makes sense, and I'm not just rambling. :)
Thanks.
There is nothing stopping you from maintaining your own cache:
var cache = [];
function locate(el) {
// search for the element within our cache.
for (var i=0;i<cache.length;i++) {
if (cache[i].elem === el) {
return cache[i].data;
};
};
// if we get this far, it isn't in the cache: add it and return it.
return cache[cache.push({
elem: el,
data: {}
}) - 1].data;
};
// used to add data to an element and store it in our cache.
function storeData(el, data) {
var store = locate(el);
for (var x in data) {
store[x] = data[x];
};
};
// used to retrieve all data stored about the target element.
function getData(el) {
return locate(el);
};
and then use as follows:
storeData(document.getElementById("foo"), {
something: 4,
else: "bar"
});
var data = getData(document.getElementById("foo"));
alert(data.something); // "4";
Objects in JavaScript (unlike classical OOP languages) can be augmented. There's nothing wrong with that; that's the way JavaScript was designed to be used:
Write:
document.getElementById( 'foo' ).customAttribute = 5;
Read:
alert( document.getElementById( 'foo' ).customAttribute );
If you don't want to alter the original object, the only way to point at it is using a dictionary as pointed out in one of the previous answers; however, you don't need to do a linear search to find the object: it can be done in logarithmic time providing you use an ID per element (potentially not its HTML ID but a custom one)
I have a function that takes a string object name and I need the function to create an new instance of a object that has the same name as the value of the string
For example,
function Foo(){}
function create(name){
return new name();
}
create('Foo'); //should be equivalent to new Foo();
While I know this would be possible via eval, it would be good to try and avoid using it. I am also interested if anyone has an alternative ideas to the problem (below)
I have a database and a set of (using classical OO methodology) classes, roughly one for each table that define common operations on that table. (Very similar to Zend_Db for those who use PHP). As everything is asynchronous doing tasks based on the result of the last one can lead to very indented code
var table1 = new Table1Db();
table1.doFoo({
success:function(){
var table2 = new Table2Db();
table2.doBar({
notFound:function(){
doStuff();
}
});
}
});
The obvious solution is to create helper methods that abstracts the asynchronous nature of the code.
Db.using(db) //the database object
.require('Table1', 'doFoo', 'success') //table name, function, excpected callback
.require('Table2', 'doBar', 'notFound')
.then(doStuff);
Which simplifies things. However the problem is that I need to be able to create the table classes, the names of which can be inferred from the first augment passed to require which leads me to the problem above...
Why not simply pass the constructor function into the require method? That way you sidestep the whole issue of converting from name to function. Your example would then look like:
Db.using(db) //the database object
.require(Table1Db, 'doFoo', 'success') //table constructor, function name, expected callback
.require(Table2Db, 'doBar', 'notFound')
.then(doStuff);
However, if you really want to use a string...
Why are you deadset on avoiding using eval? It is a tool in the language and every tool has its purpose (just as every tool can be misused). If you're concerned about allowing arbitrary execution, a simple regular expression test should render your usage safe.
If you're dead-set on avoiding eval and if all of your constructor functions are created in the default global scope (i.e. the window object), this would work:
function create(name) {
return new window[name]();
}
If you want to get fancy and support namespace objects (i.e. create('MyCompany.MyLibrary.MyObject'), you could do something like this:
function create(name) {
var current,
parts,
constructorName;
parts = name.split('.');
constructorName = parts[parts.length - 1];
current = window;
for (var i = 0; i < parts.length - 1; i++) {
current = current[parts[i]];
}
return new current[constructorName]();
}
You were at the gate of completeness. While Annabelle's solution let's you to do what's you've just wanted in the way you wanted (passing strings), let me offer you an alternative. (passing function references)
function Foo(){}
function create(name){
return new name();
}
create(Foo); // IS equivalent to new Foo();
And voila, it works :) I told you. You were at the doorsteps of the solution.
What happened is that you've try to do this
new 'Foo'()
Which doesn't makes much sense, does it? But now you pass the function by reference so the line return new name(); will be transformed into return new Foo(); just how you would expect.
And now the doors are opened to abstract the asynchronousness of your application. Have fun!
Appendix: Functions are first-class objects, which means that they can be stored by reference, passed as an argument by reference or returned by another function as values.