首页 > 解决方案 > 类方法的异步回调

问题描述

我正在用 JavaScript 编写一个类,它将发送一个对指定 URL 的 HTTP 请求,然后返回响应的正文。我是 Node.js 和 JavaScript 的新手,因此,我很难理解 Nodejs 的回调和异步特性。

我编写了获取 URL 的实际方法,它工作正常。结果可通过 Mocha 测试。

class HttpObject {
  constructor () {
    this.url = null
    this.userAgent = null
    this.body = null
  }

  fetchUrl (url, userAgent, callback) {
    this.url = url
    this.userAgent = userAgent

    const request = require('request')
    request(this.url, { timeout: 10000 }, function (error, response, body) {
      if (!error && response.statusCode === 200) {

        //the next line doesn't work, the 'body' field in Mocha test is null
        this.body = response.body
        return callback(response, false)
      } else {
        return callback(null, error)
      }
    })
  }
}

但是当我测试 HttpObject 的 body 字段时,它仍然被赋值null。不过,它应该被分配给结果的主体。

it('should send and http request to https://www.google.com', function (done) {
  httpObj.fetchUrl('https://www.google.com', 'Mozilla/5.0', (res, err) => {
    assert.strictEqual(httpObj.getUrl(), 'https://www.google.com')
    assert.strictEqual(httpObj.getPort(), 80)
    assert.strictEqual(httpObj.getUserAgent(), 'Mozilla/5.0')

    // previous tests pass, but the following doesn't
    assert.notStrictEqual(httpObj.getBody(), null)

    done()
  })
})

标签: javascriptnode.jsasynchronouscallback

解决方案


this问题是当从创建该函数的类外部调用函数时,上下文会丢失。(主要是回调)

在您的情况下,因为function (error, response, body)是从其他地方调用的,所以它不知道this.

要解决这个问题,您可以使用fat arrow如下函数:

request(this.url, { timeout: 10000 }, (error, response, body) => {
    // you can now set this.body here safely
})

或者您可以.bind(this)在回调中使用

request(this.url, { timeout: 10000 }, function (error, response, body) {
    // you can now set this.body here safely
}.bind(this))

推荐阅读