【问题标题】:Accessing 'this' of an object inside promise callback (then)在 Promise 回调中访问对象的“this”(然后)
【发布时间】:2016-03-26 16:42:22
【问题描述】:

我想用 Javascript 创建一个对象。

其中一个方法应该执行一个承诺链。链中的每个方法都必须访问作为对象成员的配置变量。 问题是,this 运算符在 PromiseMethod2 中更改,我无法访问配置变量(它在 PromiseMethod1 中正常工作)。

这是我的代码:

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!');
}

我想在链中使用方法委托而不是仅仅执行:

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

我不能使用bind 方法,因为它看起来在执行回调时会重新绑定。

有解决办法吗? 为什么PromiseMethod1 和PromiseMethod2 有区别?

【问题讨论】:

  • 你如何解决SomePromise?
  • 每种方法可能做不同的事情。大多数情况下,我使用'new Promise(resolve,reject)'然后解决(somePrams)。或者我使用第三方承诺,如 ElasticSearch 或 Request-Promise
  • 你断言你不能使用bind,但是你试过了吗?看起来这是正确的解决方案。
  • 嗨。是的,我试过了。没用。
  • 请准确展示您的尝试。

标签: javascript node.js promise


【解决方案1】:

我的真正建议是不要使用this或new(如果你仍然想要继承,你可以使用Object.create): p>

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

在这里,我使用了闭包,以及它们封装其父词法范围的变量的能力,这对我来说是有利的。而不是依靠JavaScript在运行时根据调用函数的对象神奇地将this注入我的函数,因为正如您的问题所证明的那样,这并不总是有效。

但是,我知道这是一种非常规的工作方式,所以如果你宁愿坚持使用 this,你需要使用 bind 来告诉 JavaScript 哪个神奇的 this-value 函数所属:

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)); //<- :(

在您的示例SomeMethod 中,您实际上并未使用bind。您仍然需要绑定,因为您将函数传递给.then(f),而接收函数的代码不再知道它应该为this 使用哪个对象。现在再看看我之前推荐的代码。那里没有thisses,所以这些函数根本不依赖于它们被调用的对象,你可以将它们作为高阶函数传递给你,而不必@ 987654335@ 或that = this。 :)

【讨论】:

    【解决方案2】:

    我会说这是不可能的。您尝试混合使用 2 种不同的方法:method chaining 和 promises chaining。我建议检查您的架构。

    如果您可以完全控制要使用的所有 Promise,唯一可见的事情(但我个人不喜欢它)是通过整个 Promise 链传递配置值。

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

    然后你就可以打电话了:

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

    但同样,它看起来不是一个好的代码......

    【讨论】:

    • 没有方法链接。所有方法都在 SomeObject 下。我试过这种方法,问题是 Promise reolve 方法不支持超过 1 个参数。
    • 是的,但是你想一个一个地调用同一个对象的方法。如果您真的需要异步代码 - 我建议将您的异步操作放入单独的对象/层/组件/任何东西中,并使用简单的 Promise 链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 2012-12-14
    • 2023-03-09
    • 1970-01-01
    • 2021-11-03
    • 2016-07-20
    相关资源
    最近更新 更多