【问题标题】:How to use object methods as callbacks to modify object properties in javascript如何使用对象方法作为回调来修改javascript中的对象属性
【发布时间】:2017-05-07 07:39:30
【问题描述】:

我正在构建一个到 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
};

【问题讨论】:

    标签: javascript node.js asynchronous callback request


    【解决方案1】:

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

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

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

    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 方法“替换”为同一方法的新版本,其中上下文始终是引用类的 this

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多