无法在 node.js 对象原型函数中获取 'this'
Can't get 'this' in node.js object prototype function
我正在尝试将我的一些代码包装到节点模块中,但是出现了问题。
我的测试代码:
var Twitter_Client = require('./src/twitter-client');
var twitterClient = new Twitter_Client({
consumer_key : '',
consumer_secret : '',
access_token_key : '',
access_token_secret : ''
});
twitterClient.tweet([{path: 'some_path', type: 'image/jpg'}],'test');
我的模块是这样的:
var Twitter = require('twitter');
var fs = require('fs');
var Promise = require("bluebird");
function Twitter_Client(opts){
if (!(this instanceof Twitter_Client))
return new Twitter_Client(opts);
this._client = new Twitter(opts);
this._tray = [];
}
Twitter_Client.prototype.makePost = (endpoint, params)=>{
...
};
Twitter_Client.prototype.uploadMedia = (path, type)=>{
...
};
Twitter_Client.prototype.tweet = (medias, status)=>{
var that = this;
console.log(this instanceof Twitter_Client);
return (()=>{
if (!Array.isArray(medias) || medias.length == 0) {
return Promise.resolve([]);
} else {
return Promise.resolve(medias).map((media) => {
return that.uploadMedia(media.path, media.type);
});
}
})().then((mediaids) => {
return new Promise((resolve,reject)=>{
that._client.post('statuses/update', {
status : status,
media_ids : mediaids.join(',')
}, function (error, tweet, response) {
if (error) {
reject(error);
}
resolve(tweet);
});
});
});
};
module.exports = Twitter_Client;
这个模块有3个函数,但是如果我post全部都太长了,所以我只展示其中一个被测试代码调用的函数。
当我 运行 上面的代码给了我:
false
Unhandled rejection TypeError: that.uploadMedia is not a function
我似乎没有从 'this' 获得正确的对象。
我读过很多类似的问题,似乎我正在以正确的方式创建对象并从对象而不是实例调用函数。
我的代码有什么问题?
问题是您将方法定义为粗箭头函数。由于粗箭头函数的工作方式,这意味着 this
值来自模块中的本地上下文,而不是来自调用该方法的对象。所以,改变这个:
Twitter_Client.prototype.tweet = (medias, status)=>{
对此:
Twitter_Client.prototype.tweet = function(medias, status){
并且,也更改所有其他方法。这是一个永远不应该使用粗箭头函数的地方,因为它们明确地破坏了对象方法的 this
值。
仅供参考,因为看起来您正在使用 Bluebird 承诺,您可以更改此设置:
return Promise.resolve(medias).map((media) => {
return that.uploadMedia(media.path, media.type);
});
对此:
return Promise.map(medias, (media) => {
return that.uploadMedia(media.path, media.type);
});
我正在尝试将我的一些代码包装到节点模块中,但是出现了问题。
我的测试代码:
var Twitter_Client = require('./src/twitter-client');
var twitterClient = new Twitter_Client({
consumer_key : '',
consumer_secret : '',
access_token_key : '',
access_token_secret : ''
});
twitterClient.tweet([{path: 'some_path', type: 'image/jpg'}],'test');
我的模块是这样的:
var Twitter = require('twitter');
var fs = require('fs');
var Promise = require("bluebird");
function Twitter_Client(opts){
if (!(this instanceof Twitter_Client))
return new Twitter_Client(opts);
this._client = new Twitter(opts);
this._tray = [];
}
Twitter_Client.prototype.makePost = (endpoint, params)=>{
...
};
Twitter_Client.prototype.uploadMedia = (path, type)=>{
...
};
Twitter_Client.prototype.tweet = (medias, status)=>{
var that = this;
console.log(this instanceof Twitter_Client);
return (()=>{
if (!Array.isArray(medias) || medias.length == 0) {
return Promise.resolve([]);
} else {
return Promise.resolve(medias).map((media) => {
return that.uploadMedia(media.path, media.type);
});
}
})().then((mediaids) => {
return new Promise((resolve,reject)=>{
that._client.post('statuses/update', {
status : status,
media_ids : mediaids.join(',')
}, function (error, tweet, response) {
if (error) {
reject(error);
}
resolve(tweet);
});
});
});
};
module.exports = Twitter_Client;
这个模块有3个函数,但是如果我post全部都太长了,所以我只展示其中一个被测试代码调用的函数。 当我 运行 上面的代码给了我:
false
Unhandled rejection TypeError: that.uploadMedia is not a function
我似乎没有从 'this' 获得正确的对象。 我读过很多类似的问题,似乎我正在以正确的方式创建对象并从对象而不是实例调用函数。 我的代码有什么问题?
问题是您将方法定义为粗箭头函数。由于粗箭头函数的工作方式,这意味着 this
值来自模块中的本地上下文,而不是来自调用该方法的对象。所以,改变这个:
Twitter_Client.prototype.tweet = (medias, status)=>{
对此:
Twitter_Client.prototype.tweet = function(medias, status){
并且,也更改所有其他方法。这是一个永远不应该使用粗箭头函数的地方,因为它们明确地破坏了对象方法的 this
值。
仅供参考,因为看起来您正在使用 Bluebird 承诺,您可以更改此设置:
return Promise.resolve(medias).map((media) => {
return that.uploadMedia(media.path, media.type);
});
对此:
return Promise.map(medias, (media) => {
return that.uploadMedia(media.path, media.type);
});