【问题标题】:Losing scope inside of Promise [duplicate]在 Promise 内部失去范围 [重复]
【发布时间】:2018-02-26 22:06:24
【问题描述】:

我的课程设计和承诺存在一些问题。我正在尝试通过递归调用我的 promise cb 来监听更改变量。当 networkResponse 返回一个有效(非空)令牌时,我正在尝试解决它,否则它将通过在每次调用中延迟 500 毫秒来检查 500 次。

这是我现在简化的课程:

class Tokenizer {
    constructor(page) {
        this.page = page;
        this.token = null;
        this.tries = 500;
        this.page.on('response', this.onNetworkResponse.bind(this));
    }
    async onNetworkResponse(response) {
        if (condition) {
            let resp = await response.text();
            let regex = /access_token=([\w\d]+)/g;
            let _token = regex.exec(response);
            this.token = _token[1];
        }
    }

    getToken() {
        return new Promise(function cb(resolve, reject) {
            console.log(this.tries + ' remaining');
            if (--this.tries > 0 && !this.token) setTimeout(() => cb(resolve, reject), 500);
            else (this.tries <= 0) ? reject('Try') : resolve(this.token);
        });
    }
}

我这样称呼承诺:

const t = new Tokenizer();

let test = async () => {
   let token = await t.getToken();
}

test();

但是我在 cb 函数中失去了这个范围。如果有人能回答这个问题,我将不胜感激

对于谁有这样的问题,我刚刚更新了我的 getToken 函数,如下所示:

  getToken() {
    var cb = (resolve, reject) => {
      console.log(this.tries);
      if (--this.tries > 0 && !this.token) setTimeout(() => cb(resolve, reject), 500);
      else (this.tries <= 0) ? reject('Try') : resolve(this.token);
    }
    return new Promise(cb);
  }

【问题讨论】:

  • 是的,只是不要使用function cb,而是使用箭头函数。

标签: scope promise async-await es6-class puppeteer


【解决方案1】:

您正在失去作用域,因为当您从 setTimeout 调用 cb 时,它会更改上下文。您可以使用箭头函数或.bind, (this) 解决该问题,但我将建议一种与setTimeout() 无关的稍微不同的方法,我希望它对您的需求有用:

class Tokenizer {
  constructor(page) {
    this.page = page;
    this.token = null;
    this.tries = 500;
    this.subscriber = null
    this.page.on('response', this.onNetworkResponse.bind(this));
  }
  async onNetworkResponse(response) {
    if (condition) {
      let resp = await response.text();
      let regex = /access_token=([\w\d]+)/g;
      let _token = regex.exec(response);
      this.token = _token[1];
      // Is some function waiting for the token? Call it
      if (typeof this.subscriber === 'function') {
        this.subscriber(_token[1])
        this.subscriber = null
      }
    }
  }

  getToken = () => {
    return new Promise((resolve, reject) => {
      // Is the token already available? Return it
      if (this.token) {
        resolve(this.token)
        // Token not available yet? Tell the tokenizer we are waiting for it.
      } else {
        this.subscriber(resolve)
      }
    });
  }
}

【讨论】:

  • 这实际上不起作用,因为承诺执行器中的 this 仍然不是实例
  • 你是对的,我的错。更新了代码。
  • 不是那个! function cb 是问题所在,而不是 getToken 是一种方法。 (现在这在 ES6 中也是无效的语法)
  • 是的,它是 ES2017。
  • 在 ES9 草案中,不在 ES8 标准中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-14
  • 2014-05-08
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多