【问题标题】:Can't put prototype functions in promise resolve? [duplicate]不能将原型函数放入 Promise 解析? [复制]
【发布时间】:2015-09-26 18:42:34
【问题描述】:

使用 Node.js 的 Q library,当我尝试在 promise 中将对象原型函数传递给 .then 解析器时,它会丢失 this 的上下文:

Foo.prototype.outsideResolve = function() {
    var that = this;
    return q.Promise(function(resolve, reject) {
        console.log(that); // {data: "foo"}
        resolve();
    });
};

Foo.prototype.insideResolve = function() {
    var that = this;
    return q.Promise(function(resolve, reject) {
        console.log(that); // undefined
        resolve();
    });
};

Foo.prototype.async = function() {
    var foo = this;

    return q.Promise(function(resolve, reject) {
        foo.outsideResolve()
            .then(foo.insideResolve)
            .then(resolve)
            .fail(reject)
            .done();
    });
};

为什么会这样?这是预期的行为吗?你不应该能够在承诺解析中调用原型函数吗?有没有办法解决这个问题?

【问题讨论】:

  • .then(this.insideResolve.bind(this))

标签: javascript node.js promise


【解决方案1】:

this 不是静态的。它可以根据调用 this 的函数而改变。在某些情况下,这可能是您刚刚在其上调用 new 的对象,但在这种情况下,它不是。

当您从承诺链到达foo.insideResolve 时,ThisBinding 将丢失。为了解决这个问题,您可以使用 Function.prototype.bind 方法,该方法接受可变数量的参数 - 第一个参数是您要绑定要使用的函数的 this 上下文,其他参数是部分应用的参数。 bind 函数返回一个函数,该函数在调用时会将 this 和参数传递给原始函数。

简而言之:

使用foo.insideResolve.bind(foo) 而不是foo.insideResolve

【讨论】:

  • 感谢您和 elclanrs。使用.bind 确实可以解决问题。但我仍然对为什么 this 上下文在承诺解析中丢失感到困惑。如果我们有对foo 的引用并且我们显然在调用fooinsideResolve 函数,那么this 不应该仍然评估该对象吗?
  • 这有点难以解释,但基本上没有。我不能很好地解释它,但有一个 excellent blog post 可能会有所帮助。不过,总而言之,您基本上不想依赖 this 成为某个值(这就是为什么有些人更愿意避免使用 this 的原因)。
  • 问题是,当您编写foo.insideResolve 时,您保留对 foo 的引用(没有括号来调用该函数)。您仅获得对 insideResolve 函数本身的引用,而您通过 foo 的属性找到该引用的事实丢失了。在函数内部,this 在函数被调用 时确定,而不是在您之前获得对该函数的引用时确定。 Promise 调用 insideResolve,但并不知道它是 foo 的属性;它在调用时所拥有的只是函数本身。
  • 这就是bind 修复它的原因。正如您在 Dan 的代码中看到的,传递给 bind 的参数是对最终调用函数时要使用的对象的引用。 bind 将该引用保存在一个闭包中,并在它为您调用原始函数时使用它。
  • 谢谢!这是有道理的。
猜你喜欢
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
相关资源
最近更新 更多