ctw
ctw

Reputation: 23

Can't get 'this' in node.js object prototype function

I am trying to wrap some of my codes into node module but there is a problem occurred.

My testing code:

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');

My module looks like this:

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;

There are three functions of this module but it will be too long if I post all so I am only showing one of those which is called by the testing code. When I run the code above it gives me:

false
Unhandled rejection TypeError: that.uploadMedia is not a function

It seems that I am not getting a correct object from 'this'. I have read many similar question and seems that I am creating an object in a right way and calling the function from the object instead of the instance. What's wrong with my code?

Upvotes: 0

Views: 52

Answers (1)

jfriend00
jfriend00

Reputation: 707386

The problem is that you're defining methods as fat arrow functions. Because of the way fat arrow functions work, that means that the this value comes from the local context in your module, NOT from the object that you called the method on. So, change this:

Twitter_Client.prototype.tweet = (medias, status)=>{

to this:

Twitter_Client.prototype.tweet = function(medias, status){

And, change all your other methods too. This is one place that fat arrow functions should never be used because they explicitly break the this value for object methods.


FYI, since it looks like you're using Bluebird promises, you can change this:

        return Promise.resolve(medias).map((media) => {
            return that.uploadMedia(media.path, media.type);
        });

to this:

        return Promise.map(medias, (media) => {
            return that.uploadMedia(media.path, media.type);
        });

Upvotes: 2

Related Questions