admin管理员组文章数量:1287484
I am trying to call method test in method connect of the same class. But all I am getting is "Uncaught Type Error: Cannot read property 'test' of undefined". How do I access any variables inside of sftp callback? Why is it so?
Here is my code:
const SSH2 = require('ssh2').Client;
class SshClient {
constructor(host, username, password) {
this.host = host;
this.username = username;
this.password = password;
this.port = 22;
this.client = null;
}
test(testvar) {
console.log(testvar);
}
connect() {
this.client = new SSH2();
let client = this.client;
let username = this.username;
this.client.connect({
host: this.host,
port: this.port,
username: this.username,
password: this.password
});
this.client.on('ready', function() {
console.log('Client :: ready', client);
client.sftp(function(err, sftp) {
if (err) throw err;
sftp.readdir('/home/' + username, function(err, list) {
if (err) throw err;
console.dir(list);
this.test('hey');
client.end();
});
});
});
}
}
let ssh = new SshClient('host', 'username', 'password');
ssh.connect();
I am trying to call method test in method connect of the same class. But all I am getting is "Uncaught Type Error: Cannot read property 'test' of undefined". How do I access any variables inside of sftp callback? Why is it so?
Here is my code:
const SSH2 = require('ssh2').Client;
class SshClient {
constructor(host, username, password) {
this.host = host;
this.username = username;
this.password = password;
this.port = 22;
this.client = null;
}
test(testvar) {
console.log(testvar);
}
connect() {
this.client = new SSH2();
let client = this.client;
let username = this.username;
this.client.connect({
host: this.host,
port: this.port,
username: this.username,
password: this.password
});
this.client.on('ready', function() {
console.log('Client :: ready', client);
client.sftp(function(err, sftp) {
if (err) throw err;
sftp.readdir('/home/' + username, function(err, list) {
if (err) throw err;
console.dir(list);
this.test('hey');
client.end();
});
});
});
}
}
let ssh = new SshClient('host', 'username', 'password');
ssh.connect();
Share
Improve this question
asked Nov 23, 2017 at 13:04
juldepoljuldepol
1431 gold badge3 silver badges9 bronze badges
1
- Use : var root = self at the begging of class. After in sub methods use root.test() – Nikola Lukic Commented Nov 23, 2017 at 13:09
2 Answers
Reset to default 8When using function() {
you are getting into a new context which is not your class context. Using es6 arrow functions
, you can easily share your class context into inner functions.
this.client.on('ready', () => {
client.sftp((err, sftp) => {
if (err) throw err;
sftp.readdir('/home/' + username, (err, list) => {
if (err) throw err;
this.test('hey');
client.end();
});
});
});
Here is a good article about how es6 arrow functions
works and how they affect this
.
When you use the function as a callback (passing it as an argument to another function), the this
variable inside the callback is not pointing to your object.
If you define callbacks separately, it'll be clearer:
class SshClient {
constructor(host, username, password) {
//...
}
test(testvar) {
console.log(testvar);
}
connect() {
this.client = new SSH2();
// ...
this.client.on('ready', onReadyCallback);
}
}
function onReadyCallback() {
console.log('Client :: ready', client);
client.sftp(sftpCallback);
}
function sftpCallback(err, sftp) {
if (err) throw err;
sftp.readdir('/home/' + username, readdirCallback);
}
function readdirCallback(err, list) {
if (err) throw err;
console.dir(list);
this.test('hey'); // It is clear that `this` here doesn't refer
// to the SshClient object
client.end();
});
As you can see, this
in the readdirCallback
doesn't look right anymore, the function is not a part of the SshClient
class and this
can not point to the SshClient
object.
The simplest solution is to do the same thing you do with client
and username
variables in your code - save this
into additional variable:
connect() {
this.client = new SSH2();
let self = this;
// ...
this.client.on('ready', function() {
// we can use "self" variable here,
// as it's avaialbe from the outer scope
self.client; // we can refer to client and username
self.username;
self.test(); // and we can call object methods
});
}
One more alternative is to keep the callbacks separate and catch your object into additional closure:
class SshClient {
connect() {
this.client = new SSH2();
// ...
this.client.on('ready', getOnReadyCallback(this));
}
}
function getOnReadyCallback(sshClient) {
function onReadyCallback() {
console.log('Client :: ready', sshClient.client);
sshClient.client.sftp(getSftpCallback(sshClient));
}
}
The arrow functions mentioned in the other answer are probably the best solution as you don't need any workarounds, but you have to clearly understand what the issue is and why arrow functions solve it:
An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.
The arrow function doesn't have own this
- so if you use arrow function as a callback the original object's this
stays available.
本文标签: javascriptNot able to call method within another method of the same class JSStack Overflow
版权声明:本文标题:javascript - Not able to call method within another method of the same class JS - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741275410a2369697.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论