0

I have 3 methods

exports.getImageById = function (resultFn, id) {
 ...
}

exports.getCollectionById = function (resultFn, id) {
}

in the third method I want to call both methods

exports.getCollectionImages = function (resultFn, collectionId) {

var arr = new Array();

this.getCollectionById(   // fine, 1st call
    function (result) {
        var images = result.image;
        for (i = 0; i < images.length; i++) {
            this.getImageById(function (result1) {   // error, 2nd call
                    arr[i] = result1;
                }, images[i]
            );

         }
    }
    , collectionId
);

resultFn(arr);
}

I can call first function this.getCollectionById but it fails to call this.getImageById, it says undefined function, whats the reason for that?

Sleiman Jneidi
  • 22,907
  • 14
  • 56
  • 77

2 Answers2

4

When you call this.getCollectionById passing it a callback, the callback doesn't have access to the same this

The simplest solution is to save this as a local variable.

exports.getCollectionImages = function (resultFn, collectionId) {    
    var arr = new Array();        
    var me = this; // Save this
    this.getCollectionById(   // fine, 1st call
        function (result) {
            var images = result.image;
            for (var i = 0; i < images.length; i++) {
                // Use me instead of this
                me.getImageById(function (result1) {   // error, 2nd call
                    arr[i] = result1;
                }, images[i]);
            }
        }, collectionId);
    resultFn(arr);
}
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • Thank you for this, it seems that javascript is pure instance oriented language – Sleiman Jneidi Dec 07 '12 at 18:24
  • 2
    A more accurate description is that methods in JavaScript are not bound to an instance, it depends on how they are called. – Ruan Mendes Dec 07 '12 at 18:25
  • @sleimanjneidi is your `getImageById` asynchronous? If so, the value of `i` will be wrong (the last value of i in the loop) in the callback to `me.getImageById` – Ruan Mendes Dec 08 '12 at 18:16
2

The value of this inside the inner function is not the same object as outside, because it's determined depending on how the function is called. You can find a detailed explanation in the MDN article on this.

One of the ways to solve it is by keeping a reference to the outer this in another variable such as that:

var that = this;
this.getCollectionById(   // fine, 1st call
    function (result) {
        var images = result.image;
        for (i = 0; i < images.length; i++) {
            that.getImageById(function (result1) {   // 2nd call
                    arr[i] = result1;
                }, images[i]
            );

        }
    }
    , collectionId
);
bfavaretto
  • 71,580
  • 16
  • 111
  • 150