如何从用作回调的其他类方法访问方法



我有以下Javascript类:

class App {
    log_text(text) {
        console.log(text)
    }
    process_response(response) {
        this.log_text(response) // Uncaught TypeError: this.log_text is not a function
        // self.log_text(response) // Uncaught TypeError: self.log_text is not a function
    }
    do_stuff() {
        this.log_text('hello') // OK
    }
    fetch_data() {
        jQuery.get('http://example.com/data/sample.txt', this.process_response, 'text')
    }
}

调用方法do_stuff时,我可以通过调用this.log_text来访问log_text。但是,方法 process_response (用作jQuery.get的回调处理程序)失败,因为this表示该上下文中完全不同的对象。

同样,self.log_text也会抛出 TypeError。

process_response调用log_text的可能(或正确)方法是什么,如本例所示?

正在发生的事情是你正在传递你的process_response函数,仅此而已,正如你已经看到这个变化的上下文。一种解决方法是使用箭头语法包装它,这将在 jQuery 触发回调时保留此值。

 fetch_data() {
        jQuery.get('http://example.com/data/sample.txt', (r)=> this.process_response(r), 'text')
    }

您可以使用

Function.bind()来设置process_response函数的上下文

fetch_data() {
  jQuery.get('http://example.com/data/sample.txt', this.process_response.bind(this), 'text')
}

您可以使用

箭头函数,该函数具有词法this -

fetch_data() {
  jQuery.get
    ( 'http://example.com/data/sample.txt'
    , r => this.process_response(r)
    , 'text'
    )
}

或者使用将上下文(以及可选的一些参数)绑定到函数的Function#bind -

fetch_data() {
  jQuery.get
    ( 'http://example.com/data/sample.txt'
    , this.process_response.bind(this)
    , 'text'
    )
}

或者像历史上所做的那样,用var保留上下文;现在,这比上述技术更不受欢迎 -

fetch_data() {
  var ctx = this
  jQuery.get
    ( 'http://example.com/data/sample.txt'
    , function (r) { ctx.process_response(r) }
    , 'text'
    )
}

但是,新的JS功能将改善您的生活质量。考虑强制你的 jqXHR 遵守承诺,这样你就可以使用asyncawait -

const get = (opts = {}) =>
  new Promise
    ( (resolve, reject) =>
        $.get(opts)
         .done((req, status, res) => resolve(res))
         .fail((req, status, err) => reject(err))
    )

结果是代码更扁平,许多无关的函数(如 fetch_dataprocess_response)不再需要。更好的是,我们的思想从思考绑定功能和动态上下文中解放出来——

class App {
    log_text(text) {
        console.log(text)
    }
    async main () {
      const res = await
        get ({ url: '/data/sample.txt', dataType: 'text' })
      this.log_text(res)
    }
}

您甚至可以为get包装器设置默认选项 -

const defaultOpts =
  { dataType: 'text' }
const get = (opts = {}) =>
  new Promise
    ( (resolve, reject) =>
        $.get({ ...defaultOpts, ...opts })
         .done((req, status, res) => resolve(res))
         .fail((req, status, err) => reject(err))
    )

然后使用它——

async main () {
  const res = await
    get ({ url: '/data/sample.txt' })
  this.log_text(res)
  // ...
}

最新更新