2016-12-21 62 views
0

我正在構建REST API的接口,並且在使用javascript模塊的過程中,我發現嘗試從回調中返回值時遇到了問題。請求不會以這種方式工作,並且您必須處理回調中的數據。如何使用對象方法作爲回調來修改javascript中的對象屬性

但我需要處理和比較來自多個請求的數據,所以我決定從我的回調中將數據推送到某個數據庫對象。

我做了一個原型函數被稱爲回調,以保持數據結構模塊化。

我很困惑,因爲當我嘗試從我的回調函數中修改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

這是一個衆所周知的「怪癖」的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

相關問題