node-js原型对象'self'var没有为回调存储正确的上下文
node js prototype object 'self' var does not store correct context for callback
我是一名经验丰富的开发人员,但对java脚本和nodejs还很陌生,如果这个问题的答案是"原样",我很抱歉,但尽管我已经看过多个示例和stackoverflow的答案,但我没有找到一个简单完整的原型类示例,该示例具有正确的"self"var作用域和绑定(this)。我两次都试过了,但都错了。。。我会感谢你的帮助。我试着把var self=this;在我的函数声明的开头,但在运行时,当它被设置为原型时,它实际上并没有通过函数代码,因此,"this"的设置不正确。
/**
* Module Dependencies
*/
var cheerio = require('cheerio');
var http = require('http');
/**
* Export
*/
module.exports = SimplePageGetter;
function SimplePageGetter(pageLink) {
this._pageLink = pageLink;
}
SimplePageGetter.prototype.getPage = function () {
var self = this;
http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
};
SimplePageGetter.prototype._resultsPageHttpGetCallback = function (response) {
var pageBody = '';
var self = this;
//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
self._parsePage(pageBody);
});
};
SimplePageGetter.prototype._parsePage = function (body) {
console.log('page parsed');
}
出于某种原因,在调用getPage时"self"是正确的,但它将是http模块ClientRequest,而不是_resultsPageHttpGetCallBack上的对象。我做错了什么?
谢谢你,
James
在调用函数中设置self
不会改变被调用函数中的this
。看看这个:
SimplePageGetter.prototype.getPage = function () {
var self = this;
http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
};
这仍然只是将对self._resultsPageHttpGetCallback
函数的引用传递给http.request
。http.request
仍然将其作为一个普通函数而不是方法来调用,因此_resultsPageHttpGetCallback
中的this
将是未定义的(严格模式)或全局对象(松散模式)。
self
模式用于在同一作用域(或嵌套作用域)中创建的函数,例如:
function someMethod() {
var self = this;
http.request(self._pageLink, function(err, data) {
// Use `self` here to access object info
}).end();
}
这是因为我传递到http.request
中的匿名函数关闭了创建它的上下文,并且该上下文具有self
变量,因此该函数可以访问self
变量。
对于你正在做的事情,Function#bind
会更合适:
SimplePageGetter.prototype.getPage = function () {
http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};
Function#bind
创建一个新函数,该函数在被调用时将调用this
设置为特定值的原始函数。
关于this
:的更多信息
- 关于Stack Overflow:
this
关键字是如何工作的 - 在我贫血的小博客上:神话方法|你必须记住
this
仅供参考,以下是应用于完整代码的Function#bind
模式示例:
/**
* Module Dependencies
*/
var cheerio = require('cheerio');
var http = require('http');
/**
* Export
*/
module.exports = SimplePageGetter;
function SimplePageGetter(pageLink) {
this._pageLink = pageLink;
}
SimplePageGetter.prototype.getPage = function () {
http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};
SimplePageGetter.prototype._resultsPageHttpGetCallback = function (response) {
var pageBody = '';
response.on('data', function (chunk) {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
this._parsePage(pageBody);
}.bind(this));
};
SimplePageGetter.prototype._parsePage = function (body) {
console.log('page parsed');
};
您可能会了解ES2015(又名ES6)的新功能,其中许多功能从v4起就可以在NodeJS中使用,因为底层V8引擎支持它们(或者,您可以使用transiler从ES6输入生成ES5代码)。
以下是上面使用ES2015的:
。。。箭头函数,从定义它们的上下文继承
this
,使self
不必要。。。。
class
关键字,它提供了一种更简洁的方法来编写构造函数和原型。。。。
let
关键字,因为它是ES2015代码。:-)
应用这些:
/**
* Module Dependencies
*/
let cheerio = require('cheerio');
let http = require('http');
class SimplePageGetter {
constructor(pageLink) {
this._pageLink = pageLink;
}
getPage() {
http.request(this._pageLink, response => {
this._resultsPageHttpGetCallback(response);
}).end();
}
_resultsPageHttpGetCallback(response) {
let pageBody = '';
response.on('data', chunk => {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', () => {
this.parsePage(pageBody);
});
}
_parsePage(body) {
console.log('page parsed');
}
}
/**
* Export
*/
module.exports = SimplePageGetter;
注意,class
不像函数声明那样被提升,所以导出的标准位置通常在模块的底部。如果你只有一个出口(就像你在这种情况下看起来的那样),你可以做
module.exports = class SimplePageGetter {
//...
};
最后但同样重要的是:除非你真的需要_resultsPageHttpGetCallback
和_parsePage
作为对象的属性(它们是公共的),否则我可能会让它们成为私有函数,它们要么接受SimplePageGetter
实例作为标准参数,要么期望用引用它的this
来调用,即使它们不是方法。
在这里,他们提出了一个论点:
/**
* Module Dependencies
*/
let cheerio = require('cheerio');
let http = require('http');
class SimplePageGetter {
constructor(pageLink) {
this._pageLink = pageLink;
}
getPage() {
http.request(this._pageLink, response => {
resultsPageHttpGetCallback(this, response);
}).end();
}
}
function resultsPageHttpGetCallback(getter, response) {
let pageBody = '';
response.on('data', chunk => {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', () => {
parsePage(getter, pageBody);
});
}
function parsePage(getter, body) {
console.log('page parsed');
}
/**
* Export
*/
module.exports = SimplePageGetter;
在这里,他们期望设置this
,所以我们通过Function#call
:调用他们
/**
* Module Dependencies
*/
let cheerio = require('cheerio');
let http = require('http');
class SimplePageGetter {
constructor(pageLink) {
this._pageLink = pageLink;
}
getPage() {
http.request(this._pageLink, response => {
resultsPageHttpGetCallback.call(this, response);
}).end();
}
}
function resultsPageHttpGetCallback(response) {
let pageBody = '';
response.on('data', chunk => {
pageBody += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', () => {
parsePage.call(this, pageBody);
});
}
function parsePage(body) {
console.log('page parsed');
}
/**
* Export
*/
module.exports = SimplePageGetter;
- AngularJS:我可以跳过函数参数回调吗
- 要求未定义JS回调参数
- MeteorJS:在带有回调的vzaar api上正确使用wrapAsync
- 自引用回调
- 测试Angular Service解决错误回调中的promise
- Javascript使用本地存储,回调对象并用Json更改为一个字符串以用于填充函数
- 存储在对象中的函数的回调
- Node.JS- R,Python大量计算识别回调何时返回并存储该结果
- ExtJS 6 访问消息属性在存储同步的回调
- Dojo :如何使用回调方法在 jsonRest 存储上发出 PUT 请求
- node-js原型对象'self'var没有为回调存储正确的上下文
- 回调中的数据未存储在js中的数组中
- jQuery存储要在回调中使用的任意元素数据
- 使用匿名函数和存储在变量中的函数作为回调参数
- 如何从AJAX回调中的setTimeout()中调用存储在一组选项中的函数
- Google map:显示以下教程的错误,用于存储地理代码结果并回调它们以创建地图
- jQuery.ajax()成功回调存储数据返回
- 如何创建回调函数并存储变量的值
- Javascript变量作用域,存储内容以在回调中使用它
- 如何在回调时在express中存储数据