如何解决像async和request这样的节点库的'this'问题

ask*_*ike 9 this libraries node.js

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

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

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

async.parallel([ getTwitterData, getKloutData ], function() {
    console.log('done');
});
Run Code Online (Sandbox Code Playgroud)

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

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 */ });
};
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为异步和请求会更改此上下文.我能绕过它的唯一方法是绑定我通过异步和请求传递的所有内容:

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);
};
Run Code Online (Sandbox Code Playgroud)

我做了一些基本的错误或者什么吗?我认为恢复脚本并将其分配给child_processes会产生很多开销.

Ric*_*asi 9

你这样做是完全正确的.

另一种方法是始终在上下文中保持对对象的引用而不是使用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);
};
Run Code Online (Sandbox Code Playgroud)

您也可以事先进行绑定:

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');
    });
};
Run Code Online (Sandbox Code Playgroud)

  • Underscore库有一个名为`bindAll`的便捷功能,可以减少痛苦.如果您选择CoffeeScript,您可以使用胖箭头定义方法,您根本不需要进行任何显式绑定. (3认同)