Reputation: 24063
I am using node.js. I have this handlers.js file:
exports.Handlers = function(prefix) {
this.prefix = prefix;
this.db = new DBInstance();
};
exports.Handlers.prototype.getItemById = function(id) {
var item = this.db.getItemById(id, function(error, item) {
item.name = this.prefix + item.name;
...
...
});
};
When I call:
var h = new Handlers();
h.getItemById(5);
I get an error since the context isn't the Handlers and this.prefix doesn't exists. I can fix it using this:
exports.Handlers.prototype.getItemById = function(id) {
var scope = this;
var item = this.db.getItemById(id, function(error, item) {
item.name = scope.prefix + item.name;
...
...
});
};
Is there any better way to pass the context to the callback? What is the nodejs common way to pass the context to the callback?
Upvotes: 5
Views: 14282
Reputation: 19609
Node implements ECMAScript 5, which has Function.bind()
.
I think that is what you are looking for.
exports.Handlers.prototype.getItemById = function(id) {
var item = this.db.getItemById(id, (function(error, item) {
item.name = this.prefix + item.name;
...
...
}).bind(this)); //bind context to function
};
This works, however when using a closure as a callback, like you are doing, the most common way this is done is by storing the context in a variable that can be used in the closure.
This method is more common because many times callbacks can be deep and calling bind
on each callback can be heavy; whereas defining self
once is easy:
SomeObject.prototype.method = function(id, cb) {
var self = this;
this.getSomething(id, function(something) {
//self is still in scope
self.getSomethingElse(something.id, function(selse) {
//self is still in scope and I didn't need to bind twice
self.gotThemAll(selse.id, cb);
});
});
};
Upvotes: 18
Reputation: 8945
That is the common way. You will find your scope
var named self
or _self
.
Later edit:
If you want to call a function within another context, this is the way:
getItemById.call(context, vars);
Upvotes: -2
Reputation: 150624
This problem is not related to Node.js, it's a general problem in JavaScript - and you already figured out the usual solution in JavaScript: Bind the this
context to another variable (the one that you called scope
), and use that within the callback to access the outer context.
Common names for this variable include that
and self
.
There may be a solution in ECMAScript 6 (codename "harmony") with the so-called fat-arrow operator that binds a function to an outer context. If you want to play with it today you might want to check out TypeScript, a pre-compiler for JavaScript made by Microsoft which focuses on ES6-compatible syntax. Then your callback becomes something such as
foo(() => { console.log(this.bar); });
instead of:
var that = this;
foo(function () { console.log(that.bar); });
Just for the sake of completeness: jQuery's (and other frameworks) bind
function generally works similar. See http://api.jquery.com/bind/ for an example.
HTH.
Upvotes: 1