admin管理员组

文章数量:1333478

I want to create an object in Javascript.

One of the methods should execute a promise chain. Each of the methods in the chain have to access a config variable that is a member of the object. The problem is, the this operator is changed in PromiseMethod2 and I can't access the config variable (It works correctly in PromiseMethod1).

Here's 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 the method delegate in the chain instead of just executing:

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

I can't use the bind method because it looks like it gets rebinded when the callback is executed.

Is there a solution to this? Why's there a difference between PromiseMethod1 and PromiseMethod2?

I want to create an object in Javascript.

One of the methods should execute a promise chain. Each of the methods in the chain have to access a config variable that is a member of the object. The problem is, the this operator is changed in PromiseMethod2 and I can't access the config variable (It works correctly in PromiseMethod1).

Here's 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 the method delegate in the chain instead of just executing:

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

I can't use the bind method because it looks like it gets rebinded when the callback is executed.

Is there a solution to this? Why's there a difference between PromiseMethod1 and PromiseMethod2?

Share Improve this question edited May 23, 2016 at 21:28 Michael Gaskill 8,04210 gold badges39 silver badges44 bronze badges asked Dec 20, 2015 at 13:41 shudimashudima 4601 gold badge5 silver badges9 bronze badges 5
  • How do you resolve SomePromise ? – Kiril Commented Dec 20, 2015 at 13:51
  • Each method may do different thing. Mostly I use 'new Promise(resolve,reject)' and then resolve(somePrams). Or I use a third party promise like ElasticSearch or Request-Promise – shudima Commented Dec 20, 2015 at 13:53
  • You assert that you can't use bind, but have you tried? Looks like it's the right solution. – Roamer-1888 Commented Dec 20, 2015 at 23:15
  • Hi. Yes, I tried. Didnt work. – shudima Commented Dec 21, 2015 at 8:52
  • Please show exactly what you tried. – Roamer-1888 Commented Dec 21, 2015 at 9:02
Add a ment  | 

2 Answers 2

Reset to default 1

My real remendation 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'm using closures, and their ability to enclose variables of their parent lexical scope, to my advantage. Rather than relying on JavaScript to magically inject a this into my function at run-time based on which object the function is called on, because as demonstrated by your problem, that doesn't always work.

However, I know that its an unconventional way to work, so if you'd rather stick with this, you'll need to use bind in order to tell JavaScript which magical this-value 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 example SomeMethod you're not actually using bind. You still need to bind because you're passing the function into .then(f), and the code which receives the function doesn't know anymore which object it should use for the this. Now look at my earlier remended code again. There are no thisses in there, so those functions don't rely at all on which object they're being called on, you can pass them around as higher-order-functions as much as you want without ever having to bind or that = this. :)

I would say that's impossible. You try to mix 2 different approaches: method chaining and promises chaining. I'd remend to review your architecture.

The only visible thing (but personally I don't like it) if you have a full control over all promises that you want to use is to pass config values through the whole promises chain.

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'll be able to call:

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

But again, it doesn't look like a good code...

本文标签: javascriptAccessing 39this39 of an object inside promise callback (then)Stack Overflow