Access to the 'this' object inside promise a callback (then)

I want to create an object in Javascript.

One method is to keep a promise chain. Each of the methods in the chain must access a configuration variable that is a member of the object. The problem is that the this statement is changed in PromiseMethod2 , and I cannot access the configuration variable (it works correctly in PromiseMethod1 ).

Here is my code:

 var SomeObject(config) { var that = this; that.config = config; } SomeObject.prototype.SomeMethod = function() { var that = this; that.PromiseMethod1() .then(that.PromiseMethod2) .catch(console.error); } SomeObject.prototype.PromiseMethod1 = function() { var that = this; config = that.config; return SomePromise(); } SomeObject.prototype.PromiseMethod2 = function(someParams) { var that = this; config = that.config; params = someParams; return SomePromise(); } var someObject = new SomeObject(someConfig); someObject.SomeMethod().then(function () { console.log('Done!'); } 

I want to use a method delegate in a chain, and not just execute:

  that.PromiseMethod1().then(function(response) { return that.PromiseMethod2(that, response); }; 

I cannot use the bind method because it looks like it is recovering from a callback.

Is there a solution? Why is there a difference between PromiseMethod1 and PromiseMethod2 ?

+6
source share
2 answers

My real recommendation is not to use this or new at all (and you can use Object.create if you still want inheritance):

 var SomeObject = function(config) { return { PromiseMethod1: function(){ return somePromise(config.foo); }, PromiseMethod2: function(x){ return someOtherPromise(config.bar, x); } } } var instance = SomeObject({config: true}); instance.PromiseMethod1().then(instance.PromiseMethod2); 

Here I use closure and their ability to enclose variables of their parent lexical domain in my favor. Instead of relying on JavaScript to magically inject this into my function at runtime, based on which object the function is called on, because, as your problem shows, this does not always work.

However, I know that this is an unusual way of working, so if you prefer to stick with this , you will need to use bind to tell JavaScript which magical this means the function belongs to:

 var SomeObject function(config) { this.config = config; } SomeObject.prototype.PromiseMethod1 = function(){ return somePromise(this.config.foo); } SomeObject.prototype.PromiseMethod1 = function(x){ return someOtherPromise(this.config.bar, x); } var instance = new SomeObject({config: true}); instance.PromiseMethod1().then(instance.PromiseMethod2.bind(instance)); //<- :( 

In your SomeMethod example SomeMethod you are not actually using bind . You still need to bind because you pass the function to .then(f) , and the code that receives this function no longer knows which object it should use for this . Now take a look at my previously recommended code. this ses is not there, so these functions do not rely at all on the object they call on, you can pass them as functions of a higher order as much as you want, without having bind or that = this . :)

+1
source

I would say that this is impossible. You are trying to mix two different approaches: method chain and promises chaining . I would recommend considering your architecture.

The only visible thing (but I personally donโ€™t like it), if you have full control over all the promises that you want to use, is to pass the configuration values โ€‹โ€‹through a whole chain of promises.

 SomeObject.prototype.init = function() { var that = this; return new Promise(function(resolve, reject) { resolve(that.config) }); } SomeObject.prototype.PromiseMethod1 = function(config, params) { return SomePromise(config, params); } SomeObject.prototype.PromiseMethod2 = function(config, someParams) { return SomePromise(config, someParams); } SomePromise = function(config, params) { return new Promise(function(resolve, reject) { //some code here resolve(config, newParamsFromSomeCode) }); } 

Then you can call:

 that.init().then(that.PromiseMethod1).then(that.PromiseMethod2); 

But then again, this doesn't seem like good code ...

0
source

All Articles