9

我编写了一个节点脚本,它通过请求 REST API 数据(使用库请求)来获取一些数据。它由几个函数组成,如下所示:

var data = { /* object to store all data */ },
function getKloutData() {
  request(url, function() { /* store data */}
}
// and a function for twitter data

因为我想在获取所有内容后做一些事情,所以我使用库 async 来运行所有获取函数,如下所示:

async.parallel([ getTwitterData, getKloutData ], function() {
    console.log('done');
});

这一切都很好,但是我想把所有东西都放在一个对象模式中,这样我就可以同时获取多个帐户:

function Fetcher(name) { 
    this.userID = ''
    this.user = { /* data */ }
    this.init();
}
Fetcher.prototype.init = function() {
    async.parallel([ this.getTwitterData, this.getKloutData ], function() {
        console.log('done');
    });
}
Fetcher.prototype.getKloutData = function(callback) {
    request(url, function () { /* store data */ });
};

这不起作用,因为 async 和 request 更改了 this 上下文。我可以绕过它的唯一方法是绑定我通过异步和请求传递的所有内容:

Fetcher.prototype.init = function() {
    async.parallel([ this.getTwitterData.bind(this), this.getKloutData.bind(this) ], function() {
        console.log('done');
    });
}
Fetcher.prototype.getKloutData = function(callback) {
    function saveData() {
        /* store data */
    }


    request(url, saveData.bind(this);
};

我是在做一些基本的错误还是什么?我认为恢复到脚本并将其分叉到 child_processes 会产生很多开销。

4

3 回答 3

9

你做得完全正确。

另一种方法是始终在上下文中保留对对象的引用而不是 using bind,但这需要一些技巧:

Fetcher.prototype.init = function() {
    var self = this;
    async.parallel([
        function(){ return self.getTwitterData() },
        function(){ return self.getKloutData() }
    ], function() {
        console.log('done');
    });
}

Fetcher.prototype.getKloutData = function(callback) {
    var self = this;

    function saveData() {
        // store data
        self.blah();
    }

    request(url, saveData);
};

您也可以事先进行绑定:

Fetcher.prototype.bindAll = function(){
    this.getKloutData = this.prototype.getKloutData.bind(this);
    this.getTwitterData = this.prototype.getTwitterData.bind(this);
};

Fetcher.prototype.init = function(){
    this.bindAll();
    async.parallel([ this.getTwitterData, this.getKloutData ], function() {
        console.log('done');
    });
};
于 2012-07-11T09:01:47.373 回答
3

您可以将其保存到另一个变量中:

var me = this;

然后me是你的this.

于 2012-07-11T09:00:07.290 回答
0

使用此函数实例化对象:

function newClass(klass) {
    var obj = new klass;

    $.map(obj, function(value, key) {
        if (typeof  value == "function") {
            obj[key] = value.bind(obj);
        }
    });

    return obj;
}

这将自动绑定所有函数,因此当对象内部的方法具有其对象的上下文时,您将以习惯 OOP 样式获取对象。

所以你实例化你的对象不是通过:

var obj = new Fetcher();

但:

var obj = newClass(Fetcher);
于 2014-12-06T16:21:03.563 回答