I am having a really, really hard time trying call an object function inside of an asynchronous soap request. It basically boils down to this:
function Thing(request, response) {
this.foo = function() {
console.log("this is foo");
}
this.doThing = function() {
// Get SOAP args
args = { foo: this.request.cookies.foo };
// From the SOAP npm package library
soap.createClient(function(err, client) {
client.doSomething(args, function(err, result) {
// Somehow call foo(); <--- CAN'T FIND A WAY TO DO THIS
});
});
}
}
// Make it so I can access this.request and this.response somehow
Thing.prototype = Object.create(AbstractThing);
I have tried many things, but I believe it fundamentally es down to the fact that I cannot call this.foo()
inside any of the asychrenous soap functions. Although I can pass a callback function into createClient
, like so:
function Thing(request, response) {
this.foo = function() {
console.log("this is foo");
}
this.sendSoap = function(err, client) {
// Get SOAP args
args = {
foo: this.request.cookies.foo <--- this.cookies undefined
};
client.doSomething(args, function(err, result) {
// Somehow call foo(); <--- CAN'T FIND A WAY TO DO THIS
});
}
this.doThing = function() {
// From the SOAP npm package library
soap.createClient(this.sendSoap);
}
}
// Make it so I can access this.request and this.response somehow
Thing.prototype = Object.create(AbstractThing);
I can no longer access this.request.cookies because this
is now called inside of the sendSoap
closure. I don't know why javascript makes functions as objects but I'm getting slightly frustrated.
I've tried many, many things and can't figure out a way to do this and need to because the original call to foo
is actually a recursive function I'm using in a state-itterator pattern to do authentication in a SOAP web service I've written in Java.
The last way that I can think of doing this is to modify the SOAP npm package so that I can pass this.cookies
to createClient
instead of just the callback.
I'm really all out of ideas. Any help would be greatly appreciated.
I am having a really, really hard time trying call an object function inside of an asynchronous soap request. It basically boils down to this:
function Thing(request, response) {
this.foo = function() {
console.log("this is foo");
}
this.doThing = function() {
// Get SOAP args
args = { foo: this.request.cookies.foo };
// From the SOAP npm package library
soap.createClient(function(err, client) {
client.doSomething(args, function(err, result) {
// Somehow call foo(); <--- CAN'T FIND A WAY TO DO THIS
});
});
}
}
// Make it so I can access this.request and this.response somehow
Thing.prototype = Object.create(AbstractThing);
I have tried many things, but I believe it fundamentally es down to the fact that I cannot call this.foo()
inside any of the asychrenous soap functions. Although I can pass a callback function into createClient
, like so:
function Thing(request, response) {
this.foo = function() {
console.log("this is foo");
}
this.sendSoap = function(err, client) {
// Get SOAP args
args = {
foo: this.request.cookies.foo <--- this.cookies undefined
};
client.doSomething(args, function(err, result) {
// Somehow call foo(); <--- CAN'T FIND A WAY TO DO THIS
});
}
this.doThing = function() {
// From the SOAP npm package library
soap.createClient(this.sendSoap);
}
}
// Make it so I can access this.request and this.response somehow
Thing.prototype = Object.create(AbstractThing);
I can no longer access this.request.cookies because this
is now called inside of the sendSoap
closure. I don't know why javascript makes functions as objects but I'm getting slightly frustrated.
I've tried many, many things and can't figure out a way to do this and need to because the original call to foo
is actually a recursive function I'm using in a state-itterator pattern to do authentication in a SOAP web service I've written in Java.
The last way that I can think of doing this is to modify the SOAP npm package so that I can pass this.cookies
to createClient
instead of just the callback.
I'm really all out of ideas. Any help would be greatly appreciated.
Share Improve this question asked May 10, 2016 at 0:19 Alexander KleinhansAlexander Kleinhans 6,27813 gold badges66 silver badges119 bronze badges2 Answers
Reset to default 6The reason why is that this
in the callback function will typically refer to the global window scope.
this
is a mon source of pain in JS developers and more often than not it doesn't refer to what you think it may. You can search the full details online.
Why not closure it like this?
function Thing(request, response) {
this.foo = function() {
console.log("this is foo");
}
this.doThing = function() {
var self = this; //Closure to the Thing function
// Get SOAP args
args = { foo: this.request.cookies.foo };
// From the SOAP npm package library
soap.createClient(function(err, client) {
client.doSomething(args, function(err, result) {
self.foo();
});
});
}
}
Multiple options for a working solution.
A. Declaring nested functions as named functions, or assigning anonymous functions to named variable within the closure, allows nested functions to be called by any other function within the closure without using this
. E.G.
// Either naming a function:
function foo () { console.log("foo")
// or assigning it to a named variable:
var foo = function() { console.log("foo")};
allows the function be called as foo()
inside the closure.
B. Declaring a variable set to the this
value during Thing
object construction allows functions within the closure to access their instance object using the variable name. This is the same technique contained in the answer from Philip:
`var self = this;`
C. Use anonymous arrow functions assigned to named variables. They can be called from other nested functions in the closure using the variable name. Arrow functions bind the this
value from when and where they were declared. Hence arrow functions can access their Thing
object instance using this
without the need of a separate self
variable alias. E.G.
var foo = () => {console.log(this.message)};
this.message = "foo was here";
foo(); // logs 'foo was here'
D. Of course set any parameters, nested functions or data values which must be accessed outside the closure as object properties.
// inside constructor
var foo = () => { /* whatever */ }; // callable within closure as foo()
this.foo = foo;
// outside constructor
var thing = new Thing( arg1, arg2);
thing.foo(); // callable outside closure as thing.foo()
E) Parameters passed to Thing
when called as a constructor are accessible within the closure simply by using the parameter name. For setting up a name value pair object from a request cookies object you may need an object initialiser without this
args = {
foo: request.cookies.foo // request is a parameter
};