简体   繁体   English

无法通过回调设置类成员变量

[英]Can't set class member variable from callback

I'm trying to set a class member variable from a callback of a function I'm calling from the class constructor. 我正在尝试从我从类构造函数调用的函数的回调中设置类成员变量。

To be a bit more specific: I need to set the connection ID in the Connection class constructor based on the Redis INCR result (each client has a 'global' connection ID so I can have multiple nodes). 更具体一点:我需要根据Redis INCR结果在Connection类构造函数中设置连接ID(每个客户端都有一个“全局”连接ID,因此我可以有多个节点)。

Here's the code. 这是代码。

class Connection {
  constructor() {
    client.incr('conn_id', (err, reply) => {
      this.connID = reply;
    });
  }
}

var lovely = new Connection();
console.log(`lovely connID is ${ lovely.connID }`);

This is the result: lovely connID is undefined 结果是: lovely connID is undefined

It seems that client.incr('conn_id' ....) is async , which means the callback will be invoked after your code run . 似乎client.incr('conn_id'....)是异步的,这意味着在代码运行后将调用回调。

So 所以

console.log( lovely connID is ${ lovely.connID } ); console.log( lovely connID is ${ lovely.connID } ); will be called before the callback 将在回调之前被调用

(err, reply) => { self.connID = reply; (错误,回复)=> {self.connID =回复; } }

which is similar to this : 这类似于:

class Connection{
  constructor(){
    self=this;
    setTimeout( function(){self.client='somevalue';
                          console.log('value1');}, 10)

  }
}

var a = new Connection();

console.log(a.client); 

running this will result 运行此将导致

undefined value1 未定义的值1

As others here have mentioned, the issue seems to be that client.incr is asynchronous and your code does not wait for it to resolve before accessing the properties. 正如这里的其他人所提到的,问题似乎是client.incr是异步的,并且您的代码在访问属性之前不等待它解决。 To remedy this issue, you could try passing in an onReady callback to Connection to enssure the properties will be there before trying to access them. 要解决此问题,您可以尝试将onReady回调传递给Connection以确保在尝试访问属性之前,这些属性将在那里。 Something along these lines: 遵循以下原则:

 'use strict'; // mock client.incr var client = { incr: (id, callback) => { setTimeout(() => callback(null, 'Hello World'), 0) }}; class Connection { // receive an "onReady" function constructor(onReady) { client.incr('conn_id', (err, reply) => { this.connID = reply; // call "onReady" function, and pass it the class if (typeof onReady === 'function') onReady(this) }); } } new Connection(lovely => { console.log(lovely.connID) }) 

I hope that helps! 希望对您有所帮助!

In general putting heavy initialization logic in a constructor, especially if it's asynchronous, is not a good idea. 通常,在构造函数中放置繁重的初始化逻辑(尤其是异步的)不是一个好主意。 As you've found, the constructor has no way to return the information about when the initialization is finished. 如您所见,构造函数无法返回有关初始化何时完成的信息。 An alternative is to create a promise for when the connection is ready. 另一种方法是为连接准备就绪创建一个承诺。 Then, in your outside code, you can hang a then off the property to specify the code you want to trun when it's ready. 然后,在外部代码中,可以将a挂起, then关闭该属性,以指定准备好后要修剪的代码。

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 }`);

You are using this inside the callback which might not refer to the same object. 您正在回调内部使用this函数,该回调可能不会引用同一对象。 If you can set the context object as a parameter of client.incr() , try to do so. 如果可以将上下文对象设置为client.incr()的参数,请尝试这样做。 Otherwise using self is one of the common way to go around: 否则,使用self是解决问题的常见方法之一:

class Connection {
  constructor() {
    var self = this // Keep a reference to the current "this"
    client.incr('conn_id', (err, reply) => {
      self.connID = reply;
    });
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM