如何在 Promise 的 then 回调中设置 this 的上下文?

5
当我在Promise上调用resolve()时,then()内部的函数绑定到window作用域。
是否有任何方法可以设置this的上下文,例如使用Function.apply方法?

function Point(){
  var that = this;
  
  var _x = 0;
  
  this.setX = function(x){
    return new Promise((resolve, reject)=>{
        setTimeout(()=>{
            _x = x;
            resolve.apply(that); //<== set this
        }, 1000);
    });
  }

  this.getX = function(){
    return _x;
  }
}

var p = new Point();
p.setX(10).then(function(){
  console.log(this.getX()); //this === `window`
});

编辑:

详细说明,使用同步代码可以进行方法链接,只需一遍又一遍地返回相同的对象。

//this pattern
obj.method1();
obj.method2();
...


//becomes this pattern
obj.method1(10).method2(11) ...

实现链式调用
method1 = function(x){
    return this;
}

当涉及到异步操作时,您仍可以使用回调函数完成相同的操作。

obj.method1(10, function(){ this.method2(11, function(){ ...

使用回调函数的实现

method1 = function(x, cb){
    cb.apply(this);
}

我不明白为什么有人会把"接收器"函数绑定到窗口,这对我来说毫无意义,因为承诺应该类似于同步调用。

1
Promise 的发出者为什么要知道或担心下一个回调函数的上下文呢?这不是你可以或应该做的事情。你正在尝试解决错误的问题。 - deceze
它被称为“(this)上下文”或“接收器”,而不是“(变量)作用域”。而且,不能设置它。 - Bergi
只需使用“p”代替“this”。 - Bergi
在 Promise 内部返回你的变量或作用域,参数将传递到下一个 .then() - Josué Zatarain
承诺并不保证(双关语是无意的)与同步调用完全类似,更不要说方法链接了。它们最多只能让您以更类似同步的方式处理异步回调。 - deceze
显示剩余2条评论
1个回答

3

选项一:

您可以将实例传递给resolve函数,然后在回调函数中将其作为第一个参数引用。

function Point() {
  var that = this;

  var _x = 0;

  this.setX = function(x) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        _x = x;
        resolve(that); //<== set this
      }, 1000);
    });
  }

  this.getX = function() {
    return _x;
  }
}

var p = new Point();
p.setX(10).then(function(scope) {
  console.log(scope.getX());
});

选项2:

您可以绑定回调函数的作用域:

var p = new Point();
p.setX(10).then(function () {
    console.log(this.getX()); //this === `window`
}.bind(p)); // bind the scope here

function Point() {
  var that = this;

  var _x = 0;

  this.setX = function(x) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        _x = x;
        resolve.apply(that); //<== set this
      }, 1000);
    });
  };

  this.getX = function() {
    return _x;
  }
}

var p = new Point();
p.setX(10).then(function() {
  console.log(this.getX()); //this === instance of Point
}.bind(p));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接