【问题标题】:Bluebird Promise Scope蓝鸟承诺范围
【发布时间】:2014-11-06 18:38:41
【问题描述】:

我刚刚开始使用 Promise 来尝试清理一些“回调地狱”。

我决定尝试 bluebird,并在浏览器中运行它,但立即遇到了范围界定问题。

有没有办法在新的 Promise 中设置 thisArg?下面的示例显示了 Promise 解析器中的 'this' 值设置为浏览器窗口,但我希望将其设置为周围范围,以便我可以轻松访问成员变量。

我注意到有一个 .bind() 方法,但它只作用于 'then()' 方法,而不是 promise。我也意识到我可以在 promise 和 use 闭包之前使用 'var me = this',但我想尽可能避免它。

function MyObject() {
    this.value = 7;
}

MyObject.prototype.getValue = function () {
    return new Promise(function (resolve) {
        // some request/processing that takes a long time
        var result = Ajax.request(...);

        resolve({
            value: this.value,
            result: result
        });
        // 'this' is set to window instead of the instance,
        // resulting in this.value as undefined
    });
}

var obj = new MyObject();
obj.getValue().then(function (value) {
    console.log(value); // preferably outputs 7
})

【问题讨论】:

    标签: javascript promise bluebird


    【解决方案1】:

    不,没有。你当然可以use the default approaches,但你不应该这样做。

    在进行繁重的处理并异步取回值时,您希望为该值获得一个承诺。您不需要将结果值设置为原始实例的属性。

    MyObject.prototype.getValue = function () {
        return new Promise(function(resolve) {
            // lots of processing to make a `value`
            resolve(value); // no `this` at all!
        });
    };
    

    如果您想同步获取您在实例上设置的.value,则不需要Promise 构造函数。只需使用Promise.resolve 对现有值做出承诺:

    MyObject.prototype.getValue = function () {
        // TODO: lots of processing
        return Promise.resolve(this.value);
    };
    

    或者,在你的情况下,甚至是Promise.method

    // TODO: lots of processing
    MyObject.prototype.getValue = Promise.method(function () {
        return this.value;
    });
    

    【讨论】:

    • 所以我正在尝试查看一般规则,promise 应该返回 nothing 但是在其内部生成/获取什么?如果我希望使用实例上已有的值来增加返回的结果怎么办?我只是想避免反模式。我意识到我的示例可以使用 Promise.resolve,但说它想包含 this.value 以及可能是 Ajax 调用的结果。
    • 我认为你应该强调Promise.method在这里做了什么,它正好解决了这个问题。此外,如果不涉及异步计算,则返回 promise this.value 是没有意义的。
    • @BrendanAnnable 你应该使用 Promise 构造函数来编写将回调代码转换为 Promisified 代码的逻辑 - 对于你拥有 .bind 的链。
    • @BenjaminGruenbaum:我认为在这里返回承诺的原因是 TODO: lots of processing 应该在不更改返回类型 (API) 的情况下进行修复。
    • @BrendanAnnable: 是的,从 Promise 构造函数承诺返回的内容应该只是在其中生成/获取的内容 - 通常您甚至不需要使用 Promise 构造函数,但可以使用promisification 进行操作。用结果扩充实例是一种反模式,用实例值扩充结果可以在 .then() 回调(可能是绑定的)中完成 - 示例参见 t.niese 的评论答案。
    【解决方案2】:

    这更像是一个评论而不是一个答案,因为它是基于主要意见的。

    在我需要它的 rar 情况下,它在我的代码中如下所示:

    Ajax.requestAsync 在这种情况下是Ajax.request 的承诺版本。

    我知道这可能会将您的问题转移到另一个地方。

    MyObject.prototype.getValue = function () {
        return Ajax.requestAsync(...)
        .bind(this)
        .then(function(result) {
            return {
                  value: this.value,
                  result: result
                }
        });
    }
    

    或者是这样的:

     MyObject.prototype.getValue = function () {
        var returnValue = {
            value: this.value
        };
    
        return Ajax.requestAsync(...)
        .then(function(result) {
            returnValue.result = result;
            return returnValue;
        });
    }
    

    很少使用这样的结构:

    MyObject.prototype.getValue = function () {
      return Promise.all([this, Ajax.requestAsync(...)])
      .spread(function(object, result) {
          return {
            value: object.value,
            result: result
          };
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-13
      • 2015-09-06
      • 2015-02-13
      • 1970-01-01
      • 2017-01-19
      • 2017-10-10
      相关资源
      最近更新 更多