Javascript Can';t从回调中设置类成员变量
我正试图通过从类构造函数调用的函数的回调来设置类成员变量 更具体一点:我需要根据Redis INCR结果在连接类构造函数中设置连接ID(每个客户端都有一个“全局”连接ID,因此我可以有多个节点) 这是密码Javascript Can';t从回调中设置类成员变量,javascript,redis,ecmascript-6,Javascript,Redis,Ecmascript 6,我正试图通过从类构造函数调用的函数的回调来设置类成员变量 更具体一点:我需要根据Redis INCR结果在连接类构造函数中设置连接ID(每个客户端都有一个“全局”连接ID,因此我可以有多个节点) 这是密码 class Connection { constructor() { client.incr('conn_id', (err, reply) => { this.connID = reply; }); } } var lovely = new Con
class Connection {
constructor() {
client.incr('conn_id', (err, reply) => {
this.connID = reply;
});
}
}
var lovely = new Connection();
console.log(`lovely connID is ${ lovely.connID }`);
这是结果:connID未定义
似乎client.incr('conn\u id')是异步的,这意味着在代码运行后将调用回调
所以
log(可爱的connID是${lavely.connID}
);将在回调之前调用
(错误,回答)=>{
self.connID=回复;
}
与此类似:
class Connection{
constructor(){
self=this;
setTimeout( function(){self.client='somevalue';
console.log('value1');}, 10)
}
}
var a = new Connection();
console.log(a.client);
运行此命令将导致
未定义
价值1
似乎client.incr('conn_id'..)是异步的,这意味着回调将在代码运行后调用
所以
log(可爱的connID是${lavely.connID}
);将在回调之前调用
(错误,回答)=>{
self.connID=回复;
}
与此类似:
class Connection{
constructor(){
self=this;
setTimeout( function(){self.client='somevalue';
console.log('value1');}, 10)
}
}
var a = new Connection();
console.log(a.client);
运行此命令将导致
未定义
价值1
正如其他人所提到的,问题似乎在于
client.incr
是异步的,您的代码在访问属性之前不会等待它被解析。要解决此问题,您可以尝试将onReady
回调传递到Connection
,以确保在尝试访问属性之前属性将在那里。大致如下:
“严格使用”;
//mock client.incr
var客户端={incr:(id,回调)=>{
setTimeout(()=>callback(null,'Hello World'),0)
}};
类连接{
//接收“onReady”函数
构造函数(onReady){
client.incr('conn_id',(err,reply)=>{
this.connID=回复;
//调用“onReady”函数,并将其传递给类
if(typeof onReady==='function')onReady(this)
});
}
}
新连接(lovely=>{console.log(lovely.connID)}
正如其他人所提到的,问题似乎是client.incr
是异步的,您的代码在访问属性之前不会等待它的解析。要解决此问题,您可以尝试将onReady
回调传递到Connection
,以确保在尝试访问属性之前属性将在那里。大致如下:
“严格使用”;
//mock client.incr
var客户端={incr:(id,回调)=>{
setTimeout(()=>callback(null,'Hello World'),0)
}};
类连接{
//接收“onReady”函数
构造函数(onReady){
client.incr('conn_id',(err,reply)=>{
this.connID=回复;
//调用“onReady”函数,并将其传递给类
if(typeof onReady==='function')onReady(this)
});
}
}
新连接(lovely=>{console.log(lovely.connID)}
一般来说,在构造函数中放入大量的初始化逻辑,特别是异步的,不是一个好主意。正如您所发现的,构造函数无法返回初始化何时完成的信息。另一种方法是创建连接准备就绪时的承诺。然后,在外部代码中,您可以挂起一个Then
属性,以指定准备就绪时要trun的代码
class Connection {
constructor() {
this.connId = new Promise((resolve, reject) =>
client.incr('conn_id', (err, reply) => {
if (err) return reject(err);
resolve(reply);
});
}
}
var lovely = new Connection();
lovely.connId . then(connId => console.log(`lovely connID is ${ connID }`);
一般来说,在构造函数中放入大量的初始化逻辑,特别是在异步的情况下,不是一个好主意。正如您所发现的,构造函数无法返回初始化何时完成的信息。另一种方法是创建连接准备就绪时的承诺。然后,在外部代码中,您可以挂起一个
Then
属性,以指定准备就绪时要trun的代码
class Connection {
constructor() {
this.connId = new Promise((resolve, reject) =>
client.incr('conn_id', (err, reply) => {
if (err) return reject(err);
resolve(reply);
});
}
}
var lovely = new Connection();
lovely.connId . then(connId => console.log(`lovely connID is ${ connID }`);
不熟悉Redis,但它是
client.incr
异步的吗?这可能意味着在对client.incr的回调有机会运行之前,您正在运行console.log行。请参阅。您的问题不是“无法从回调中设置类成员变量”,而是“无法在设置类成员变量之前访问它”。不熟悉Redis,但是client.incr
异步的?这可能意味着您在对client.incr的回调有机会运行之前正在运行console.log行。请参阅。您的问题不是“无法从回调中设置类成员变量”,而是“无法在设置类成员变量之前访问它”。当然,那么他应该如何修复它?如果他需要记录它,他应该在回调中这样做,如果他需要做更多的事情,他可以在回调中调用一个函数;我的意思是,你的答案遗漏了这一部分,应该加以补充。从构造函数内部进行日志记录不是很好。如果我想从构造函数外部登录呢?当然,那么他应该如何修复它呢?如果他需要登录,他应该在回调中这样做,如果他需要做更多的事情,他可以在回调中调用函数,我不是在问我自己;我的意思是,你的答案遗漏了这一部分,应该加以补充。从构造函数内部进行日志记录不是很好。如果我想从构造函数之外登录呢?在这个承诺的时代,我们仍然在使用回调?如果他想访问构造函数外部的connId
,该怎么办;他怎么知道它是否准备好了呢?@torazaburo我把它看作是一种直截了当的方式,用以证明什么是错的,以及事件的顺序是如何发生的——而不是最终的实现(因此用了一句话:“……沿着……的路线的东西”)。如果OP想在了解数据流后使用承诺,那么就这样吧,他/她可以使用您的答案作为指导。感谢您提供的替代方案。在这个充满承诺的时代,我们仍然在使用回调?如果他想访问施工现场以外的connId
,该怎么办