我正在用JavaScript编写一个类,该类将发送对指定URL的HTTP请求,然后返回响应的正文。我是Node.js和JavaScript的新手,因此,我很难理解Node.js的回调和异步特性。
我写了获取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()
})
})
答案 0 :(得分:1)
问题是,从创建该函数的类外部调用函数时,上下文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))
答案 1 :(得分:0)
您的HttpObject中的this.body
语句与其余this
值的作用域不同,因为它的回调为request
。尝试在请求的回调上方添加var that = this
。
class HttpObject {
constructor () {
this.url = null
this.userAgent = null
this.body = null
}
fetchUrl (url, userAgent, callback) {
// add var that
var that = this;
this.url = url
this.userAgent = userAgent
const request = require('request')
request(this.url, { timeout: 10000 }, function (error, response, body) {
if (!error && response.statusCode === 200) {
// Change the value to that.
that.body = response.body
return callback(response, false)
} else {
return callback(null, error)
}
})
}
}