expired keys in nodeJs - javascript

I want to create some pattern for key-value store, with structure like:
function ItemObject(value1, value2, value3) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
// or whatever object needs.
}
then, I make a function like:
function keystore() {
this.keys = new Array();
this.decaytime = 50000; //in second
}
keystore.prototype.storeKey = function(key, itemObject) {
this.keys[key] = itemObject;
setTimeout(this.removeKey(key), this.decaytime);
}
keystore.prototype.removeKey = function(key) {
console.log('removing ' + key);
console.log(this.keys);
if (this.keys[key]) {
delete this.keys[key]
}
console.log('done');
console.log(this.keys);
}
module.exports = keystore;
Now, I want to make that this.keys[keyid] removed after decaytime. How can I do that? Because this.removeKey() is outside setTimeout() scope, and obviously, not a function since it is not declared yet in setTimeout. I need removeKey() as part of object because I want to remove key prematurely if needed, so I would keep removeKey()
Thank you
EDIT: I found a way, but it is ugly.
keystore.prototype.storeKey = function(key, itemObject) {
this.keys[key] = itemObject);
var _this = this;
setTimeout(function() {_this.removeKey(key);}, this.decaytime);
}
Is there any proper way?

Use arrow functions for setTimeout, your this context will be maintained.
function keystore() {
this.keys = new Array();
this.decaytime = 2000; //in second
}
keystore.prototype.storeKey = function(key, itemObject) {
this.keys.push(key, itemObject);
setTimeout(() => this.removeKey(key), this.decaytime);
}
keystore.prototype.removeKey = function(key) {
console.log('removing ' + key);
console.log(this.keys);
if (this.keys[key] != null) {
this.keys = this.keys.filter((item, index) => index !== key);
}
console.log('done');
console.log(this.keys);
}

Related

Merge two custom javascript functions

This is the first function:
jQuery.fn.serializeObject = function(){
var self = this,
json = {},
push_counters = {},
patterns = {
"validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
"key": /[a-zA-Z0-9_]+|(?=\[\])/g,
"push": /^$/,
"fixed": /^\d+$/,
"named": /^[a-zA-Z0-9_]+$/
};
this.build = function(base, key, value){
base[key] = value;
return base;
};
this.push_counter = function(key){
if(push_counters[key] === undefined){
push_counters[key] = 0;
}
return push_counters[key]++;
};
jQuery.each(jQuery(this).serializeArray(), function(){
// skip invalid keys
if(!patterns.validate.test(this.name)){
return;
}
var k,
keys = this.name.match(patterns.key),
merge = this.value,
reverse_key = this.name;
while((k = keys.pop()) !== undefined){
// adjust reverse_key
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
// push
if(k.match(patterns.push)){
merge = self.build([], self.push_counter(reverse_key), merge);
}
// fixed
else if(k.match(patterns.fixed)){
merge = self.build([], k, merge);
}
// named
else if(k.match(patterns.named)){
merge = self.build({}, k, merge);
}
}
json = jQuery.extend(true, json, merge);
});
return json;
};
This function to serialize the form's values but the problem of this function that it's not getting the value of the unchecked inputs because that I make this function:
jQuery.fn.mySerialize = function() {
var $container = jQuery(this),
$checkboxes = $container.find("input[type='checkbox']").each(function() {
jQuery(this).val(this.checked ? 1 : 0).prop('checked', true);
});
var serialized = ($container.serializeObject());
$checkboxes.each(function() {
jQuery(this).prop('checked', jQuery(this).val() == 1);
});
return serialized;
};
And it's working as I need by directly using mySerialize function now I want to merge the edits that I make at mySerialize function to the serializeObject function because I failed to do that directly into serializeObject function because that I created the mySerialize function.
Thanks in advance and really hope anyone helps me on this.

Rxjs observing object updates and changes

I am currently trying to observe any changes to a given object including all of it's elements.
The following code only fires when an object[x] is updates, but not if individually updating object[x]'s elements such as object[x][y]
<script>
var elem = document.getElementById("test1");
var log = function(x) {
elem.innerHTML += x + "<br/><br/><br/>";
};
var a = [{a:1,b:2},
{a:2,b:5}
];
var source = Rx.Observable
.ofObjectChanges(a)
.map(function(x) {
return JSON.stringify(x);
});
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1];
</script>
This code runs and fires correctly.
however. if I instead to this
a[0]['a'] = 3;
Then nothing happens.
EDIT
A better way to phrase this, how can I observe changes from an array of objects?
If you want only the nested object changes:
var source = rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
});
If you also want changes like a[0] = a[1]:
var source = rx.Observable.merge(
rx.Observable.ofArrayChanges(a),
rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
})
);
The flatMap or selectMany (they are the same function) will allow you to iterate over a value and execute a function that returns an Observable. The values from all these Observables are "flattened" onto a new stream that is returned.
http://reactivex.io/documentation/operators/flatmap.html
Perhaps something like this by merging two Observables (one for the array and the other observing the elements of the array):
var a = [
{a:1,b:2},
{a:2,b:5}
];
var source1 = Rx.Observable.ofArrayChanges(a).map(function(x) {
return JSON.stringify(x);
});
var source2 = Rx.Observable
.fromArray(a.map(function(o, i) { return [o, i]; }))
.flatMap(function(oi) {
return Rx.Observable.ofObjectChanges(oi[0])
.map(function(x) {
var y = {
type: x.type,
object: x.object,
name: x.name,
oldValue: x.oldValue,
arrayIndex: oi[1] // pass the index of the member that changed
};
return JSON.stringify(y);
});
})
source = source1.merge(source2)
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1]
a[1]['b'] = 7
Thanks to #electrichead here we're not using concatMap because the sources that we made by ofObjectChanges and ofArrayChanges never complete.
Here's a working example of Rx.Observable.ofNestedObjectChanges simple implementation, you can get the gist of it and implement you own.
http://jsbin.com/wekote/edit?js,console
Rx.Observable.ofNestedObjectChanges = function(obj) {
if (obj == null) { throw new TypeError('object must not be null or undefined.'); }
if (typeof Object.observe !== 'function' && typeof Object.unobserve !== 'function') { throw new TypeError('Object.observe is not supported on your platform') }
return new Rx.AnonymousObservable(function(observer) {
function observerFn(changes) {
for(var i = 0, len = changes.length; i < len; i++) {
observer.onNext(changes[i]);
}
}
Object.observe(obj, observerFn);
//Recursive observers hooks - same observerFn
traverseObjectTree(obj, observerFn);
function traverseObjectTree(element, observerFn){
for(var i=0;i<Object.keys(element).length;i++){
var myObj = element[Object.keys(element)[i]];
if(typeof myObj === "object"){
Object.observe(myObj, observerFn);
traverseObjectTree(myObj,observerFn);
}
}
}
return function () {
Object.unobserve(obj, observerFn);
};
});
};
//Test
var json = {
element : {
name : "Yocto",
job : {
title: "Designer"
}
},
element1: {
name : "Mokto"
}
};
setTimeout(function(){
json.element.job.title = "A Great Designer";
},3000);
var source = Rx.Observable.ofNestedObjectChanges(json);
var subscription = source.subscribe(
function (x) {
console.log(x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
json.element.name = "Candy Joe";

What is wrong with my observable pattern?

I'm testing the observable pattern in javascript. My callbacks in the array never seem to execute. What is wrong with my syntax?
<script type="text/javascript">
var Book = function (value) {
var onChanging = [];
this.name = function () {
for (var i = 0; i < onChanging.length; i++) {
onChanging[i]();
}
return value;
}
this.addTest = function (fn) {
onChanging.push(fn);
}
}
var b = new Book(13);
b.addTest(function () { console.log("executing"); return true; });
b.name = 15;
</script>
From your code above it looks like you need to call your function name instead of assigning a value something like:
var b = new Book(13);
b.addTest(function () { console.log("executing"); return true; });
b.name(); //<-- Before b.name = 15
Setting b.name = 15 doesn't execute the function, it just overwrites the value of b.name.
You could use getters and setters to react to a changing value. See John Resig's blog post or the MDN reference
I edited your code to use them:
var Book = function (value) {
this.onChanging = [];
this._name = "";
}
Book.prototype = {
addTest: function (fn) {
this.onChanging.push(fn);
},
get name() {
return this._name;
},
set name(val) {
for (var i = 0; i < this.onChanging.length; i++) {
this.onChanging[i](val);
}
this._name = val;
}
};
var b = new Book(13);
b.addTest(function (val) {
console.log("executing", val);
return true;
});
b.name = 15;
b.name = 17;
working demo.
You can also make a more generic solution that can work for all your properties without having to define the getters and setters, a lot of frameworks use this approach.
Book = function () {
this._events = [];
this._rawdata = {};
}
Book.prototype = {
bind: function (fn) {
this._events.push(fn);
},
// pass the property, and it returns its value, pass the value and it sets it!
attr: function (property, val) {
if (typeof val === "undefined") return this._rawdata[property];
this._rawdata[property] = val;
for (var i = 0; i < this._events.length; i++)
// we pass out the val and the property
this._events[i](val, property);
}
};
b = new Book();
b.bind(function (val) {
console.log("executing", val);
return true;
});
b.attr("name","The Hobbit");
b.attr("SKU" ,1700109393901);
console.log(b.attr("name")); // --> The Hobbit
http://jsfiddle.net/wv4ch6as/
Of course you would want to change the binder so that you can bind onto properties not one bind for all properties, but I think this gets the idea.

Create an object with modified versions of all methods in a source object [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
I want to create an object that has modified versions of all of the methods in a source object, but I'm having trouble using for...in.
If this is my source object:
var raw = {};
raw.add = function(a,b){return a + b;}
raw.sub = function(a,b){return a - b;}
raw.neg = function(a){return -a;}
raw.sqrt = function(a){return Math.sqrt(a);}
It works if I recreate the list of properties in an array of strings:
var mod2 = Object.create(raw);
var proplist = ["add", "sub", "neg", "sqrt"];
proplist.forEach(function(prop){
mod2[prop] = function(){
var arglist = [].slice.apply(arguments);
var out = [];
if(arglist.length == 1){
[].concat(arglist[0]).forEach(function(d){ out.push(raw[prop](d)); });
}
else if(arglist.length == 2){
[].concat(arglist[0]).forEach(function(d1){
[].concat(arglist[1]).forEach(function(d2){
out.push(raw[prop](d1,d2));
})
});
}
return out;
}
});
But my attempt to use for..in doesn't work, all of the methods in the new object will do "sqrt":
var modified = Object.create(raw);
for(prop in raw){
modified[prop] = function(){
var arglist = [].slice.apply(arguments);
var out = [];
if(arglist.length == 1){
[].concat(arglist[0]).forEach(function(d){ out.push(raw[prop](d)); });
}
else if(arglist.length == 2){
[].concat(arglist[0]).forEach(function(d1){
[].concat(arglist[1]).forEach(function(d2){
out.push(raw[prop](d1,d2));
})
});
}
return out;
}
}
What is the best way to iterate through the methods automatically?
The issue with your second implementation is that you are using prop in your new method (which will be called sometime later), but the for loop that creates prop has already run to completion by the time that method is called sometime later so prop is not the right value any more (it will always be the last property). I fixed that in my implementation by capturing prop in an IIFE (immediately invoked function expression) so it would be frozen separately for each pass through the for loop. Your first implementation doesn't have that problem because you're using .forEach() on the array of properties which uses a callback function which captures the value of prop for you automatically into a closure.
So here's the result with these changes to your implementation:
Add an IIFE to freeze the value of prop for use in the new methods.
Add an extra check to make sure the methods we're copying are not inherited and are functions.
Initialized raw to a plain object as I don't see any reason to use Object.create() here.
The code:
var raw = {};
raw.add = function(a,b){return a + b;}
raw.sub = function(a,b){return a - b;}
raw.neg = function(a){return -a;}
raw.sqrt = function(a){return Math.sqrt(a);}
var modified = {};
for (prop in raw) {
if (raw.hasOwnProperty(prop) && typeof raw[prop] === "function") {
(function (prop) {
modified[prop] = function () {
var arglist = [].slice.apply(arguments);
var out = [];
if (arglist.length == 1) {
[].concat(arglist[0]).forEach(function (d) {
out.push(raw[prop](d));
});
} else if (arglist.length == 2) {
[].concat(arglist[0]).forEach(function (d1) {
[].concat(arglist[1]).forEach(function (d2) {
out.push(raw[prop](d1, d2));
})
});
}
return out;
}
})(prop);
}
}
Working demo: http://jsfiddle.net/jfriend00/5LcLh/
<script>
var raw = {};
raw.add = function () { console.log('add default method'); }
raw.sub = function () { console.log('sub default method'); }
raw.neg = function () { console.log('neg default method'); }
raw.sqrt = function () { console.log('sqrt default method'); }
console.log('*****************');
console.log('before modifying');
console.log('*****************');
raw.add();
raw.sub();
raw.neg();
raw.sqrt();
var proplist = ["add", "sub", "neg", "sqrt"];
console.log('*****************');
console.log('after modifying');
console.log('*****************');
console.log('');
var modified = Object.create(raw);
for (prop in proplist) {
if (prop == 0)
console.log('rewriting methods and calling methods inside loop................');
modified[proplist[prop]] = function () { console.log(proplist[prop] + ' method modified, ' + proplist.length + ' argument passed') }
modified[proplist[prop]]();
}
console.log('');
console.log('trying call methods after loop is done................');
modified.add();
modified.sub();
modified.neg();
modified.sqrt();
console.log('...it is becaouse "prop" variable in loop holding last count number ' + prop);
</script>
thanks to arnold.NET.JS's response clarifying the problem, I see that closure is one way to do it:
var raw = {};
raw.add = function(a,b){return a + b;}
raw.sub = function(a,b){return a - b;}
raw.neg = function(a){return -a;}
raw.sqrt = function(a){return Math.sqrt(a);}
var mod = Object.create(raw);
for(prop in raw){
mod[prop] = (function(){
var propname = prop;
function f(){
var arglist = [].slice.apply(arguments);
var out = [];
if(arglist.length == 1){
[].concat(arglist[0]).forEach(function(d){ out.push(raw[propname](d)); });
}
else if(arglist.length == 2){
[].concat(arglist[0]).forEach(function(d1){
[].concat(arglist[1]).forEach(function(d2){
out.push(raw[propname](d1,d2));
})
});
}
return out;
}
return f;
})();
}

Why are my properties assigning incorrectly?

I created an ObservablePropertyList which is supposed to execute a callback when a property changes. The implementation is:
function ObservablePropertyList(nameCallbackCollection) {
var propertyList = {};
for (var index in nameCallbackCollection) {
var private_value = {};
propertyList["get_" + index] = function () { return private_value; }
propertyList["set_" + index] = function (value) {
// Set the value
private_value = value;
// Invoke the callback
nameCallbackCollection[index](value);
}
}
return propertyList;
}
And here's a quick test demonstration:
var boundProperties = BoundPropertyList({
TheTime: function (value) {
$('#thetime').text(value);
},
TheDate: function (value) {
$('#thedate').text(value);
}
});
var number = 0;
setInterval(function () {
boundProperties.set_TheTime(new Date());
boundProperties.set_TheDate(number++);
}, 500);
For some reason though, the properties are not being assigned correctly or something. That is, calling set_TheTime for some reason executes the callback for set_TheDate, almost as though it were binding everything to only the last item in the list. I can't for the life of me figure out what I'm doing wrong.
When using loops like that you need to wrap it in an enclosure
function ObservablePropertyList(nameCallbackCollection) {
var propertyList = {};
for (var index in nameCallbackCollection) {
(function(target){
var private_value = {};
propertyList["get_" + index] = function () { return private_value; }
propertyList["set_" + index] = function (value) {
// Set the value
private_value = value;
// Invoke the callback
target(value);
}
})(nameCallbackCollection[index]);
}
return propertyList;
}
You need to create a closure in order for each iteration of the for loop to have its own private_variable object. Otherwise, each iteration just overwrites the previous (since private_variable is hoisted to the top of its scope). I'd set it up like this:
var ObservablePropertyList = (function () {
"use strict";
var handleAccess = function (propList, key, callback) {
var privValue = {};
propList["get_" + key] = function () {
return privValue;
};
propList["set_" + key] = function (value) {
// Set the value
privValue = value;
// Invoke the callback
callback(value);
};
};
return function (coll) {
var propertyList = {}, index;
for (index in coll) {
handleAccess(propertyList, index, coll[index]);
}
return propertyList;
};
}());
var boundProperties = ObservablePropertyList({
TheTime: function (value) {
$('#thetime').text(value);
},
TheDate: function (value) {
$('#thedate').text(value);
}
}), number = 0;
setInterval(function () {
boundProperties.set_TheTime(new Date());
boundProperties.set_TheDate(number++);
}, 500);
DEMO: http://jsfiddle.net/PXHDT/

Categories

Resources