我正在构建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
};
答案 0 :(得分:2)
这是众所周知的Javascript“怪癖”:当您从myCallback
函数(或request
)调用setTimeout
函数时,上下文调用的em>是request
函数 - 这意味着this
引用request
,不到Database
对象。因此,例如,如果从DOM事件处理程序调用{{1}},则myCallback
将引用DOM元素。
现在,为了解决您的具体问题,这里有一个代码示例。我冒昧地使用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
。