如何使用对象方法作为回调来修改javascript

时间:2016-12-21 19:13:14

标签: javascript node.js asynchronous callback request

我正在构建REST API的接口,并且在使用javascript request模块的过程中,我发现尝试从回调中返回值时遇到了麻烦。请求不会以这种方式工作,您必须处理回调内的数据。

但是我需要处理和比较来自许多请求的数据,所以我决定将数据从回调中推送到某个数据库对象。

我创建了一个原型函数,作为回调来保持数据结构模块化。

我感到困惑,因为当我尝试从我的回调函数中修改this.value时,结果不会到达正确的位置。

我希望回调函数能够修改我的数据库实例,并在等待回调完成后能够在以后访问该更改。
在下面的代码示例中,我展示了我能够使用globalString完成此操作,但在globalDatabase中,赋值不会在回调函数结束后继续存在。

我怀疑我可能错误地使用了我的对象指针。任何人都可以指出我如何修改this.value的缺陷,或提供一个很好的替代我在这里使用OOP的方式。

一个好的解决方案应该能够从回调内部分配一个值,然后从另一个未被回调调用的函数中访问该值。

从回调中存储数据的最佳方法是什么?

    var Database = function(){
        console.log("<Executing constructor>");
        this.value = "initial constructor data";
    };
    Database.prototype.myCallback = function(error, response, body){
        console.log("<Executing callback>");
        this.value = body;
        globalString = body;
    };
    globalString = "blank";
    globalDatabase = new Database();
    console.log(globalString, "|" ,globalDatabase.value);
    main();
    function main(){
        var request = require('request');
        requestParams = {
            url: "http://ip.jsontest.com/",
            method: "GET",
            json: true
        };
        request(requestParams, globalDatabase.myCallback);
        console.log(globalString, "|" ,globalDatabase.value);
        setTimeout(function() {
            console.log(globalString, "|" ,globalDatabase.value);
        }, 2 * 1000);//seconds wait time for callback to finish
    };

我能够使用setTimeout中的回调来复制这个问题。

var Database = function(){
    console.log("<Executing constructor>");
    this.value = "initial constructor data";
};
Database.prototype.myCallback = function(){
    console.log("<Executing callback>");
    this.value = "callback modified data";
};
d = new Database();//global target for async modification
main();
function main(){
    console.log("First, the object contains: ",d.value);
    setTimeout(d.myCallback, 1 * 1000);//seconds wait time
    console.log("Back in main, the object contains: ", d.value);
    setTimeout(function() {
        console.log("After waiting patiently, the object contains: ",d.value);
    }, 2 * 1000);//seconds wait time
};

1 个答案:

答案 0 :(得分:2)

这是众所周知的Javascript“怪癖”:当您从myCallback函数(或request)调用setTimeout函数时,上下文request函数 - 这意味着this引用requestDatabase对象。因此,例如,如果从DOM事件处理程序调用{​​{1}},则myCallback将引用DOM元素。

有许多好的答案可以解释这一点:herehere

现在,为了解决您的具体问题,这里有一个代码示例。我冒昧地使用ES6类重写你的第二个例子,因为我觉得它更清晰:

this

注意在构造函数中调用class Database { constructor() { console.log('<Executing constructor>'); this.value = 'initial constructor data'; // bind `this` to the `myCallback` function so that whenever we call // `myCallback`, it will always have the correct `this` // this.myCallback = this.myCallback.bind(this); } myCallback() { console.log('<Executing callback>'); this.value = 'callback modified data'; } } let d = new Database(); //global target for async modification main(); function main(){ console.log("First, the object contains: ",d.value); setTimeout(d.myCallback, 1 * 1000);//seconds wait time console.log("Back in main, the object contains: ", d.value); setTimeout(function() { console.log("After waiting patiently, the object contains: ",d.value); }, 2 * 1000);//seconds wait time };。使用相同方法的新版本“替换”bind方法,其中上下文始终是引用该类的myCallback