I dont know what is the problem with my code.
// emitter.js
var EventEmitter = require('events').EventEmitter;
var util = require('util');
function Loadfun(param1, param2, db){
function __error(error, row){
if(error){
this.emit('error', error);
return true;
}
if(row.length < 1)
this.emit('failure');
}
function doSomething(){
db.query('select something', callback);
}
function callback(err, result){
if(__error(error))
return false;
else
this.emit('success', result);
}
this.doSomething = doSomething;
};
util.inherits(Loadfun,EventEmitter);
module.exports = Loadfun;
This is the emitter function.
and i am using this for some sync db works.
the following is the calling function.
var emitter = require('emitter');
router('/fetch', function(req, res){
var fetch = new emitter(param1, param2, db);
fetch.on('failure', function(){
console.log('error');
});
fetch.on('success', function(data){
console.log(JSON.stringify(data));
});
fetch.doSomething();
});
this works perfectly fine without any errors.
I tried logging the flow till the emiting of success
but the catching of the event emitting is not getting logged..
I dont understand what is the problem.. It would be nice if someone could help.
2 things that I can quickly see are:
You are passing an error if(__error(error)) which is not defined there.
You are calling this.emit in the callback function scope and it is pointing to the db.query and not the EventEmitter
You have to bind this to your callback.
Doing the following will work for you db.query('select something', callback.bind(this));
But you also have to fix your "error" mentioned in number one.
In most of your code, you are using the keyword thisin the wrong context. Every function declared with the function keyword, has its own this context, so when inside __error for example, the thisyou are referring to is not the LoadFun this and so it is not the class extending the EventEmitter class therefore does not emit anything.
You can either bind your functions when calling them, or use arrow functions, or assign to another variable, example with assigning this to another variable :
function Loadfun(param1, param2, db){
var self = this;
function __error(error, row){
if(error){
self.emit('error', error);
return true;
}
if(row.length < 1)
self.emit('failure');
}
function doSomething(){
db.query('select something', callback);
}
function callback(err, result){
if(__error(err))
return false;
else
self.emit('success', result);
}
self.doSomething = doSomething;
};
Related
How to pass the variable from outside to onResourceRequested function?
I am not able to access the variable testvar inside the callback function of onResourceRequested property.
Any idea how to fix this issue?
Below is the sample code I used for testing
var phantom = require("phantom");
var _ph, _page, _outObj;
phantom.create().then(function(ph){
_ph = ph;
return _ph.createPage();
}).then(function(page){
_page = page;
var testvar = "WHY THIS IS NOT PRINTING";
_page.property('onResourceRequested', function (req, networkRequest) {
console.log("THIS LINE WORKS");
console.log(testvar); // THIS DOESNT WORK
});
_page.property('onResourceReceived', function (res) {
//console.log('received: ' + JSON.stringify(res, undefined, 4));
});
return _page.open('https://www.ammaus.com/', function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
}
_ph.exit();
});
}).then(function(status){
console.log(status);
return _page.property('content')
}).then(function(content){
_page.close();
_ph.exit();
}).catch(function(e){
console.log(e);
});
Use arrow function (ES6) like this:
_page.property('onResourceRequested', (req, networkRequest) => {
console.log("THIS LINE WORKS");
console.log(testvar); // THIS DOESNT WORK
});
An arrow function does not newly define its own this when it's being executed in the global context; instead, the this value of the enclosing execution context is used, equivalent to treating this as closure value.
I have a javascript function "data.getOrdersByUsersModifiedDate" which is making a call to another function "database.getDb". The first function gets a "request" parameter object which has parameters defined. However I can't seem to be getting my head around as to how I can pass that parameter from data.getOrdersByUsersModifiedDate TO database.getDb so that I can use it at line
var orders = db.order.find().toArray(function(err, result)
How can I pass my request parameter from the top function "getOrdersByUsersModifiedDate" to lower function "database.getDb" so I can use it as a filter when I get orders
data.getOrdersByUsersModifiedDate = function (request, next) {
database.getDb(function(err, db) {
if(err) {
next(err);
} else {
var orders = db.order.find().toArray(function(err, result) {
if(err) return next(err);
next(null, result);
});
}
});
};
Use bind.
bind and apply allows a developer to specify the context of the function call (this).
Bind creates a new function with the arguments given to bind (from second parameter), whereas apply calls the function with the new context and the parameters passed as an array (see doc).
This will help you solve scoping hell in callback hell.
The poor man's way to achieve this is using let that=this.
Edit: As pointed by the OP in the comments, arrow functions in ES6 do not bind this ; thus using an arrow function solves the OP issue.
data.getOrdersByUsersModifiedDate = function (request, next) {
database.getDb(function(err, db) {
if(err) {
next(err);
} else {
let {arg1, arg2, arg3} = request; // This should work with ES6
var arg1 = request.arg1; // Otherwise this?
var orders = db.order.find().toArray(function(err, result) {
if(err) return next(err);
next(null, result);
});
}
}.bind(this)); // Scope this to the context of getOrdersByUsersModifiedDate
};
I just noticed if I have a method in my class I cannot access it with this keyword in my other prototypes if I call them in async.auto or... please see the sample code for more clarification and my workaround.
Would you do the same? In other words is this the most elegant way in Node.JS?
function foo(config) {
var self = Object.create(foo.prototype)
self.db = nano.db.use(config.db.dbName);
return self
}
foo.prototype.method1 = function () {
// The workaround to use this.db is to store this.db in a variable, is this elegant?!? Would you do the same?
var db = this.db;
async.auto({
check_DB: function (next) {
// do some operations here
next();
},
insert_DB: ['check_DB', function (callback, results) {
// Note1: interestingly this.db is not going to work! in other words here this.db is undefined
db.insert(value, function (err, body) {
//Do some other operations here
})
}]
});
}
foo.prototype.method2 = function () {
// The workaround to use this.db is to store this.db in a variable?!? Would you do the same?
var db = this.db;
db.get("baz", function (err, body) {
// Do some operatiuons
// Note2: interestingly this.db is not going to work here either!
db.get("bar", function (err, response) {
// do some other operations
})
}
});
}
It's exactly right. The async.auto(... function is going to change the scope of "this". It's not particular to async, but to calling a javascript function within another one.
Same deal with db.get(... in method2. It also changes the scope of "this" in the exact same way.
So it is quite normal in javascript code before calling a function where you want to access "this" from the outer scope to assign "this" to some other variable just, just as you've done with:
var db = this.db;
A lot of folks will assign this to something like: "self', "_this", "that", etc.
I have an problem and I guess the solution is using callbacks. But I'm not sure how.
When starting node.js the following code gets called:
// create a new player and insert in the database
// the player gets inserted in the database correctly
var player1 = new player();
console.log(player1.id); // undefined
My constructor looks like this:
function Player(id) {
// if we don't have a id, this player needs to be created
this.id = (typeof id !== 'number') ? this.createPlayer() : this.setId(id);
}
Then I create a player in the database:
Player.prototype.createPlayer = function () {
var playerId = 0;
connection.query("INSERT INTO players SET `created_at` = now()", function (err, result) {
if (result) {
playerId = result.insertId;
console.log("Successfully inserted player no. " + playerId);
this.id = parseInt(playerId, 10);
return this.id;
} else {
console.log("Something went wrong: " + err);
}
});
};
My guess is I need some form of callback, but I'm not sure how I will do this. A small push in the right direction would be great!
This is the use case of node.js EventEmitter. You can use events to let the application know that your object initialization is completed and it is ready to be used. (I haven't tried the code, but its should work this way, let me know if it doesn't)
var EventEmitter = require('events').EventEmitter;
var util = require('util');
// Define your class like
function Player(id) {
// if we don't have a id, this player needs to be created
this.id = (typeof id !== 'number') ? this.createPlayer() : this.setId(id);
}
util.inherits(Player, EventEmitter);
Player.prototype.createPlayer = function (cb) {
connection.query(sql, function (err, result) {
if (result) {
// to avoid triggering event before binding.
process.nextTick(function () {
// success! passing null as first argument and data as second
this.emit('load', null, this.id);
});
} else {
process.nextTick(function () {
this.emit('load', err, null); // passing err as first argument
});
}
});
};
// And, use your class like
var player1 = new player();
player1.on('load', function (err, id) {
console.log(player1.id);
});
As per you comment, createPlayer is not always called, i.e. only on certain condition. so you could use the same emit in case where you don't want to call createPlayer.
Hope that helps
In Node.js there are a number of ways to queue up a callback function. They are all documented here: http://nodejs.org/api/timers.html#timers_setimmediate_callback_arg
One example for adding two numbers and passing the result to a callback would be:
function addWithCallback(a, b, callback) {
process.setImmediate(callback, a+b);
}
Just like that you could do:
addWithCallback(1,3,foo);
and foo would be queued into the event loop and passed the result of 1+3 at execution time. Also check out:
http://howtonode.org/understanding-process-next-tick and setImmediate vs. nextTick
Definitely a complete solution to your question, but hopefully the "small push in the right direction" you wanted :)
Basically a callback is just a function to call then something is done
ie
function asyncAdd(v1,v2,callback){
var total = v1 + v2;
callback(total);
}
asyncAdd(1,2,function(t){
alert(t);
});
Contrast this with:
syncAdd(v1,v2){
return total;
}
Hopefully this should give you enough to get started.
Much better explanation here: http://recurial.com/programming/understanding-callback-functions-in-javascript/
I've recently used a nice library for node.js called Kue.
I wanted to get some better understanding of what's going so I started reading the code...
I stumbled on to a piece of code and my mind went "WTF!!?!#$#!$"...
This is the code:
function get(obj) {
var pending = 0
, res = {}
, callback
, done;
return function _(arg){
switch (typeof arg) {
case 'function':
callback = arg;
break;
case 'string':
++pending;
obj[arg](function(err, val){
if (done) return;
if (err) return done = true, callback(err);
res[arg] = val;
--pending || callback(null, res);
});
break;
}
return _;
};
}
which being used like this:
exports.stats = function(req, res){
get(queue)
('inactiveCount')
('completeCount')
('activeCount')
('failedCount')
('delayedCount')
('workTime')
(function(err, obj){
if (err) return res.send({ error: err.message });
res.send(obj);
});
};
.
.
.
Are those functions on functions?!
How are they aware of each other?
What is that '_'(underscore) on the 7th row of the function?
Could someone please help me understad what's goin' on over there? :)
Functions can indeed return functions. Take this function, for example:
function func(text) {
alert(text);
return func;
}
Obviously the return value of any invocation of func will be, again, func, so you can use it like this:
func("hello")("world");
…and you'll get two alerts: first "hello", and then "world".
Next, there's something called a named function expression. You might have seen anonymous function expressions before:
doSomething(thing, function(err) {
// operation completed or something
});
That, of course, is great for simple things, but sometimes you want the function to have a name so it can refer to itself. As Kolink mentioned, if you just want to recurse, there's arguments.callee, which refers to the function currently executing, but there is another way: you can give the function a name visible only within the function while still having it be a function expression:
doSomething(thing, function myself(err) {
// ^^^^^^
// now I can refer to myself as myself!
});
An underscore is a valid identifier, so they're basically just combining these techniques in a way that may be difficult to understand.