5

我正在使用 node.js。我有这个 handlers.js 文件:

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;
        ...
        ...
    });
};

当我打电话时:

var h = new Handlers();
h.getItemById(5);

我收到一个错误,因为上下文不是处理程序并且 this.prefix 不存在。我可以用这个来修复它:

exports.Handlers.prototype.getItemById = function(id) {
    var scope = this;
    var item = this.db.getItemById(id, function(error, item) {
        item.name = scope.prefix + item.name;
        ...
        ...
    });
};

有没有更好的方法将上下文传递给回调?将上下文传递给回调的nodejs常用方法是什么?

4

3 回答 3

18

Node 实现了 ECMAScript 5,它具有Function.bind().

我认为这就是你要找的。

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
};

这可行,但是当使用闭包作为回调时,就像您正在做的那样,最常见的方法是将上下文存储在可以在闭包中使用的变量中。

这种方法更常见,因为多次回调可能很深,bind每次回调的调用可能很重;而定义self一次很容易:

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);
        });
    });
};
于 2013-01-26T19:57:41.237 回答
1

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.

于 2013-01-26T19:33:10.440 回答
-2

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);
于 2013-01-26T19:31:42.400 回答