node-dirty doesn't persist from run to run - javascript

I have the following module :
// vote.js
var db = require(./dirty-wrapper);
module.exports = function vote() {
var obj = {};
// increase the score
obj.inc = function(key) {
var pval = db.get(key);
if (!pval) pval = 0;
db.set(key, pval + 1);
};
// decrease the score
obj.dec = function(key) {
var pval = db.get(key);
if (!pval) pval = 0;
db.set(key, pval - 1);
};
// reset the score to 0
obj.reset = function(key) {
db.set(key, 0);
};
obj.get = function(key) {
return db.get(key);
};
return obj;
};
Which uses this simple wrapper for dirty:
// dirty-wrapper.js
var dirty = require('dirty');
var db = dirty('vote.db');
module.exports = db.on('load', function() {
var obj = {};
obj.set = function(key, val, callback) {
db.set(key, val);
return callback();
};
obj.get = function(key, callback) {
return callback(db.get(key));
};
obj.reset = function(callback) {
db.forEach(function(key, val) {
val = 0;
});
return callback();
};
return obj;
});
and this is my simple client :
// client.js
var vote = require('./vote.js')();
vote.inc('michael');
vote.inc('michael');
vote.inc('michael');
vote.inc('michael');
console.log('michael: ' + vote.get('michael')); // output = michael: 4
Problem is that when the run stops and I start the client again, The output is again michael: 4
after the second run, vote.db contains the following :
$ cat vote.db
{"key":"michael","val":1}
{"key":"michael","val":4}
{"key":"michael","val":4}
{"key":"michael","val":4}
{"key":"michael","val":1}
{"key":"michael","val":4}
{"key":"michael","val":4}
{"key":"michael","val":4}
First, would be great if someone would explain the append-only strategy. Second I would like to understand why node-dirty doesn't persists even though it writes to the disk each run.
Thanks ;)

You are using the database before it has loaded, and are essentially starting from 0 every time. module.exports runs immediately, but the load event has to wait for the disk io.
You have to wait for the file to be loaded and parsed before you get values from the db.
From the readme:
dirty event: 'load' (length)
Emitted once the database file has finished loading. It is not safe to access records before this event fires. Writing records however should be fine.
You can remove the dirty-wrapper file, and just use vote as the wrapper. Make a minor change to how you are using it, keeping in mind that you have to wait for the load event.
Your vote interface:
// vote.js
var events = require('events');
var dirty = require('dirty');
var db = dirty('vote.db');
var obj = new events.EventEmitter();
// increase the score
obj.inc = function(key) {
var pval = db.get(key);
if (!pval) pval = 0;
db.set(key, pval + 1);
};
// decrease the score
obj.dec = function(key) {
var pval = db.get(key);
if (!pval) pval = 0;
db.set(key, pval - 1);
};
// reset the score to 0
obj.reset = function(key) {
db.set(key, 0);
};
obj.get = function(key) {
return db.get(key);
};
db.on('load', function() {
obj.emit('load');
});
module.exports = obj;
And your main script:
// client.js
var vote = require('./vote.js');
vote.on('load', function() {
vote.inc('michael');
vote.inc('michael');
vote.inc('michael');
vote.inc('michael');
console.log('michael: ' + vote.get('michael')); // output = michael: 4
});
This will output 4 more votes every run.

Related

Can i call multiple java script functions with in controller?

I defined a JavaScript function using a custom service and I called this function using the service in my controller. This function uses two parameters: The first one is input which I am getting by hitting the below API and the second one is the value of the year which I'm getting using ng-model directive. When I am calling this function in my controller I am getting an error like type is not defined or id is not defined etc. Is it the right way to call a JavaScript function in the controller. Please suggest me.
$http.get("http://152.144.218.70:8080/USACrime/api/crimeMultiple?city=" +$scope.strCity + "&crime=" + $scope.type1 + "&model=" + model).success(function (result) {
$scope.prograssing = false;
console.log("manisha", $scope.strCity);
console.log("kanika", result);
$scope.output = result;
console.log("monga", $scope.output);
$scope.hex = hexafy.year_city($scope.output,$scope.type);
console.log("service", $scope.hex);
});
myapp.js
var app= angular.module("myApp",["ngRoute","leaflet-directive","pb.ds.components"]);
var geomarker = new L.FeatureGroup();
app.service('hexafy', function() {
this.year_city = function (input2,years) {
if(years.toLowerCase()=="all"){
years = "2012,2013,2014,2015,2016,2017,2018,2019";
}
var yrs = years.split(",");
output = {};
outerBoundary = {};
boundary = {};
boundary["boundaryId"] = input[0]["id"];
boundary["boundaryType"] = input[0]["type"];
boundary["boundaryRef"] = "C1";
outerBoundary["boundary"] = boundary;
output["boundaries"] =outerBoundary;
themes = [];
for(var i in input){
crimeTheme = {};
crimeThemeValue = {};
crimeThemeValue["boundaryRef"] = "C1";
result = [];
for(var j in input[i]["prediction"]){
dict = {};
if(yrs.indexOf(input[i]["prediction"][j]["year"])>-1){
dict["name"] = input[i]["prediction"][j]["year"]+" "+input[i]["crime"]+" Crime";
dict["description"] = input[i]["crime"]+" Crime for "+input[i]["prediction"][j]["year"];
dict["value"] = input[i]["prediction"][j]["count"];
dict["accuracy"] = input[i]["accuracy"];
result.push(dict);
}
}
crime = input[i]["crime"].toLowerCase()+"CrimeTheme";
crimeThemeValue["individualValueVariable"] = result;
console.log('crimeThemeValue["individualValueVariable"]',crimeThemeValue["individualValueVariable"]);
crimeTheme[crime] = crimeThemeValue;
themes.push(crimeTheme);
console.log("themes",JSON.stringify(themes));
}
output["themes"] = themes;
console.log(output);
return output;
};
});
});
1) .success and .error methods are deprecated and it is not good to go with it. Instead you'd better use .then(successCallback, errorCallback)
2) To use a service method the proper way is to it like this:
app.service('myService', function() {
var service = {
method:method
};
return service;
function method() {
//Logic
}
})
So in your case the way to go is:
app.service('hexafy', function () {
return {
years_city: function (input2, years) {
if (years.toLowerCase() == "all") {
years = "2012,2013,2014,2015,2016,2017,2018,2019";
}
var yrs = years.split(",");
output = {};
outerBoundary = {};
boundary = {};
boundary["boundaryId"] = input[0]["id"];
boundary["boundaryType"] = input[0]["type"];
boundary["boundaryRef"] = "C1";
outerBoundary["boundary"] = boundary;
output["boundaries"] = outerBoundary;
themes = [];
for (var i in input) {
crimeTheme = {};
crimeThemeValue = {};
crimeThemeValue["boundaryRef"] = "C1";
result = [];
for (var j in input[i]["prediction"]) {
dict = {};
if (yrs.indexOf(input[i]["prediction"][j]["year"]) > -1) {
dict["name"] = input[i]["prediction"][j]["year"] + " " + input[i]["crime"] +
" Crime";
dict["description"] = input[i]["crime"] + " Crime for " + input[i]["prediction"]
[j]["year"];
dict["value"] = input[i]["prediction"][j]["count"];
dict["accuracy"] = input[i]["accuracy"];
result.push(dict);
}
}
crime = input[i]["crime"].toLowerCase() + "CrimeTheme";
crimeThemeValue["individualValueVariable"] = result;
console.log('crimeThemeValue["individualValueVariable"]', crimeThemeValue[
"individualValueVariable"]);
crimeTheme[crime] = crimeThemeValue;
themes.push(crimeTheme);
console.log("themes", JSON.stringify(themes));
}
output["themes"] = themes;
console.log(output);
return output;
}
}
})

How to customize autocomplete function of the CodeMirror

I want to customize an autocomplete function to Codemirror.
So I have build this code:
CodeMirror.commands.autocomplete = function (cm) {
var arrayTabNONDefault = new Array();
var stringaCampi = null;
var arrayTabellaCampo = null;
var textVal = cm.getValue();
textVal = textVal.toUpperCase();
var res = textVal.match("SELECT(.*)FROM");
if (res != null) {
stringaCampi = res[1];
arrayTabellaCampo = stringaCampi.split(",");
var nomeTab = null;
for (var i = 0; i < arrayTabellaCampo.length; i++) {
nomeTab = (arrayTabellaCampo[i].split(".")[0]).trim();
if (hintTables[nomeTab] == null)
hintTables[nomeTab] = new Array();
} //FINE FOR
} //FINE IF
CodeMirror.showHint(cm, CodeMirror.hint.sql, {
tables: hintTables
});
cm.on("beforeChange", function (cm, change) {
var before = cm.getRange({ line: 0, ch: 0 }, change.from);
var text = cm.getRange(change.from, change.to);
var after = cm.getRange(change.to, { line: cm.lineCount() + 1, ch: 0 });
if (before.indexOf("FROM") !== -1)
// alert("Ho scritto FROM");
console.log("before change", before, text, after);
});
cm.on("change", function (cm, change) {
var from = change.from;
var text = change.text.join("\n");
var removed = change.removed.join("\n");
var to = cm.posFromIndex(cm.indexFromPos(from) + text.length);
var before = cm.getRange({ line: 0, ch: 0 }, from);
var after = cm.getRange(to, { line: cm.lineCount() + 1, ch: 0 });
if (before.indexOf("FROM") !== -1)
console.log("after change", before, removed, text, after);
});
} //FINE ESTENSIONE
This is the content of hintTables
var hintTables = { "#T_TF_FilesList": ["FilesListHeaderID", "NumRecord", "FileTypeID", "FileID", "FilesListHeaderID", "NumRecord"],
"#T_TF_SelectedItems": ["EventHeaderID", "ItemType", "ItemID1", "ItemID2", "EventHeaderID", "ItemType", "ItemID1", "ItemID2"],
"#T_TFT_CacheSearchCriteriaHeaders": ["ID", "SyncDate", "FileTypeID", "CriteriaExpressionString", "CriteriaExpressionHash", "PageRecordsNumber", "PageNumber", "NumFiles"]
};
So I want that the system should propose a list of this table after I write FROM, or the system should to propose a list of stored procedures after I write EXECUTE.
It is possible to do this?
Are you trying to customize the SQL hint addon? If so, you should make changes inside sql-hint.js (under codemirror/addon/hint).
Basically what you should do is:
1.In your app.js (whatever js file for your main logic) call editor.showHint({hint: CodeMirror.hint.sql) on "change" event;
2.Inside sql-hint.js, return {list: hintTables, from: somePos, to: somePos} when the user types FROM or EXECUTE which can be detected by regular expression or inspecting the tokens at the line. I made up some code for your reference:
var cursor = editor.getCursor();
var tokenAtCursor = editor.getTokenAt(cursor);
if (tokenAtCursor.type == "FROM-and-EXECUTE")
return {list: hintTables,
from: CodeMirror.Pos(cur.line, tokenAtCursor.start),
to: CodeMirror.Pos(cur.line, tokenAtCursor.end)};
If I misunderstand your question and this answer is not helpful, please tell me and I will delete it.

NodeJS some modules not working

I'm making a game with socket.io and nodejs, and I'm making a module called rooms.js, this module require users.js module and fiveSocket.js module
but when I call Rooms.New from the main server file, it says that fiveSocket is undefined, same problem when Rooms.New calls a users.js function, I got TypeError: Cannot read property 'getSocketIDbyId' of undefined
rooms.js:
var mysql = require('../mysql/mysql.js');
var headers = require('./headers.js');
var users = require('./users.js');
var fiveSocket = require('./sockets.js');
var Rooms = {
Obj: {},
Room: function(data) {
var room = this;
this.name = data.name;
this.users = [];
this.floorCode = data.floor;
this.description = data.desc;
this.maxUsers = data.maxUsers;
this.owner = data.owner;
this.setTime = new Date().getTime();
this.dbID = data.dbID;
this.doorx = data.doorx;
this.doory = data.doory;
this.doordir = data.doordir;
},
New: function(socketID, roomID) {
var keys = Object.keys(Rooms.Obj).length;
var id = keys + 1;
var callback = function(row) {
fiveSocket.emitClient(socketID, headers.roomData, {
title: row.title,
desc: row.description,
mapStr: row.floorCode,
doorx: row.doorx,
doory: row.doory,
doordir: row.doordir
});
var uid = users.getIdBySocketID(socketID);
users.Obj[uid].curRoom = roomID;
var rid = Rooms.getIdByDbID(roomID);
Rooms.Obj[rid].users.push(uid);
}
if(Rooms.getIdByDbID(roomID) != false) {
var room = Rooms.getIdByDbID(roomID);
var row = { title: room.name, description: room.description, floorCode: room.foorCode, doorx: room.doorx, doory: room.doory, doordir: room.doordir };
callback(row);
} else {
mysql.Query('SELECT * FROM rooms WHERE id = ? LIMIT 1', roomID, function(rows) {
if(rows.length > 0) {
var row = rows[0];
Rooms.Obj[id] = new Rooms.Room({name: row.title, floorCode: row.floorCode, desc: row.description, maxUsers: row.maxUsers, owner: row.owner, dbID: row.id, doorx: row.doorx, doory: row.doory, doordir: row.doordir});
callback(row);
}
});
}
},
removeUser: function(DBroomID, userID) {
var rid = Rooms.getIdByDbID(DBroomID);
var room = Rooms.Obj[rid];
var index = room.indexOf(userID);
if (index > -1) array.splice(index, 1);
},
Listener: function(users) {
setInterval(function(){
for(var roomID in Rooms.Obj) {
var room = Rooms.Obj[roomID];
// send users coordinates
room.users.forEach(function(uid) {
var socketID = users.getSocketIDbyId(uid);
var data = Rooms.getUsersInRoomData(roomID);
fiveSocket.emitClient(socketID, headers.roomUsers, data);
});
// unload inactive rooms (no users after 10 seconds)
var activeUsers = room.users.length;
var timestamp = room.setTime;
var t = new Date(); t.setSeconds(t.getSeconds() + 10);
var time2 = t.getTime();
if(activeUsers <= 0 && timestamp < time2) {
Rooms.Remove(roomID);
}
}
}, 1);
},
getUsersInRoomData: function(roomID) {
var room = Rooms.Obj[roomID];
var obj = {};
room.users.forEach(function(uid) {
var user = users.Obj[uid];
obj[uid] = {
username: user.username,
position: user.position,
figure: user.figure
};
});
return obj;
},
Remove: function(id) {
delete Rooms.Obj[id];
},
getIdByDbID: function(dbID) {
var result = null;
for(var room in Rooms.Obj) {
var u = Rooms.Obj[room];
if(u.dbID == dbID) var result = room;
}
if(result == null) return false;
else return result;
},
getDbIDbyId: function(id) {
return Rooms.Obj[id].dbID;
}
}
Rooms.Listener();
module.exports = Rooms;
EDIT: (if it can be helpful)
When I console.log fiveSocket on the main file
When I console.log fiveSocket on the rooms.js file
EDIT2: When I've removed var users = require('./users.js'); from fiveSocket, when I console.log it in rooms.js it works, why ?
EDIT3: I still have the problem
If you need the others modules sources:
Users.JS: http://pastebin.com/Ynq9Qvi7
sockets.JS http://pastebin.com/wpmbKeAA
"Rooms" requires "Users" and vice versa, so you are trying to perform "circular dependency".
Quick search for node.js require circular dependencies gives a lot of stuff, for example :
"Circular Dependencies in modules can be tricky, and hard to debug in
node.js. If module A requires('B') before it has finished setting up
it's exports, and then module B requires('A'), it will get back an
empty object instead what A may have intended to export. It makes
logical sense that if the export of A wasn't setup, requiring it in B
results in an empty export object. All the same, it can be a pain to
debug, and not inherently obvious to developers used to having those
circular dependencies handled automatically. Fortunately, there are
rather simple approaches to resolving the issue."
or
How to deal with cyclic dependencies in Node.js

Is it possible for this code to lose some matches?

During my NodeJS learning journey I found this sample code in a book (NodeJS in Practice) which uses streams to find some matches in data coming from another stream.
var Writable = require('stream').Writable;
var util = require('util');
module.exports = CountStream;
util.inherits(CountStream, Writable);
function CountStream(matchText, options) {
Writable.call(this, options);
this.count = 0;
this.matcher = new RegExp(matchText, 'ig');
}
CountStream.prototype._write = function(chunk, encoding, cb) {
var matches = chunk.toString().match(this.matcher);
if (matches) {
this.count += matches.length;
}
cb();
};
CountStream.prototype.end = function() {
this.emit('total', this.count);
};
And the code which uses the stream:
var CountStream = require('./countstream');
var countStream = new CountStream('book');
var http = require('http');
http.get('http://www.manning.com', function(res) {
res.pipe(countStream);
});
countStream.on('total', function(count) {
console.log('Total matches:', count);
});
Isn't it possible to lose some matches, if a match breaks in two chunks of data?
For example first chunk of data contain 'This a bo' and the other chunk contains 'ok of mine.' which no one has not the book independently but the whole data contains a book.
What would be the best solution to find all matches?
So, Like I explain in my comments, if you know the max length of strings matched by your regex (to compute the max length, see the very good answer at https://stackoverflow.com/a/31173778/4114922), you could cache the previous chunk and concatenate it to the new chunk.
With this method, I think you're not going to lose any match.
var Writable = require('stream').Writable;
var util = require('util');
module.exports = CountStream;
util.inherits(CountStream, Writable);
function CountStream(matchText, maxPatternLength, options) {
Writable.call(this, options);
this.count = 0;
this.matcher = new RegExp(matchText, 'ig');
this.previousCache = undefined;
this.maxPatternLength = maxPatternLength;
}
CountStream.prototype._write = function(chunk, encoding, cb) {
var text;
if(this.previousCache === undefined) {
text = chunk.toString();
}
else {
text = this.previousCache + chunk.toString();
}
var matches = text.match(this.matcher);
if (matches) {
this.count += matches.length;
}
this.previousCache = text.substring(text.length - this.maxPatternLength);
cb();
};
CountStream.prototype.end = function() {
this.emit('total', this.count);
};

variables transaction in phantomjs, scraping web page

I need to scrape url's from one page, I have made this loop using phantomjs. But it isn't working and I don't know why.
function() {
var f = fs.open('parse.txt', 'a');
for (var x = 0; x <= 15; x++) {
var hrefs = page.evaluate(function(x) {
return $('.login').eq(x).attr('href');
}, 'hrefs');
f.write(hrefs + '\r\n');;
}
f.close();
}
I have tried to do this with an array, but it failed also.
var array = [];
page.evaluate(function(array){
for (var z = 0; z<=15; z++) {
array.push($('.login').eq(z).attr('href'));
}
}, array);
console.log(array.length); // 0
Here's what worked for me.
// var webpage = require('webpage');
var page = require('webpage').create();
var fs = require('fs');
var system = require('system');
var address = "https://jquery.org";
console.log("Opening page : " + address);
// var page = webpage.create();
page.open(address, function(status) {
console.log('Status? '+status);
if ( status !== 'success') {
console.log("Failed to load the address...");
phantom.exit();
}
var f = fs.open('parse.txt', 'a');
for (var x = 0; x<=15; x++ ) {
var href = page.evaluate(function(x) {
return $('a').eq(x).attr('href');
}, x);
console.log(href);
f.write(href + '\r\n');
}
f.close();
phantom.exit();
});
Some notes.
In the first example, you didn't need to remove "x" from function x, you needed to pass x into page.evaluate as the variable that contained the value to be passed to your function once it was in the browser.
i.e.
page.evaluate(function(x) {...}, x);
instead of
page.evaluate(function(x){...}, hrefs)
and definitely not
page.evaluate(function() { return x; })
given that understanding the appropriate way to accomplish the second example is :
var array = page.evaluate(function() {
var result = [];
for (var z = 0; z<=15; z++) {
result.push($('.login').eq(z).attr('href'));
}
return result;
});

Categories