Backbone.js $.ajax success callback inside a collection init not calling a function from the same collection

ajax, backbone.js, callback, jquery

Solution

You are misunderstanding how scoping and `this` work in JavaScript.

Calling the function like

loadPhotos(data);

will look for a function called `loadPhotos` in the various scopes from your success callback up to the global scope, but no such function exists because the function is attached to your collection instance.

this.loadPhotos(data)

is closer however it entirely depends on what `this` is referencing. `this` is a special keyword in JavaScript and the object that it points at depends on how the function was called. In your case `this` depends entirely on the behavior of jQuery. You want to use a reference to the collection. Common names to make it easier to know that the variable references the object are `self`, `that` and sometimes `_this`.

The one way to do that is a save a reference to the object pointed to by the outer `this` that references the collection. If you save it into a variable, it will work fine.

initialize: function(models, options){
    // Stuff

    var self = this;

    $.ajax({
        type: "GET",
        url: this.url,
        data: "album=" + this.albumName,
        dataType: "json",
        success: function(data){
            console.log(data);

            // Call the function on the collection.
            self.loadPhotos(data);

        },
        error: function(jqXHR, textStatus, errorThrown){
            console.log("FETCH FAILED: " + errorThrown);
        }
    });

},

Another option is to do as @alnitak's answer says, and explicitly pass the proper callback context using the `context` attribute.

Problem

I'm trying to call loadPhotos, but I get an error saying that loadPhotos is not defined. I tried `this.loadPhotos();` but then I get an error saying that the object doesn't have such a method. I'm pretty new at this and still trying to figure out what has access to what and such, and I'd greatly appreciate if someone could point me in the right direction. What am I doing wrong? Here's my code: ``` Album = Backbone.Collection.extend ({ model: Photo, url: "/api/", albumName: "", initialize: function(models, options){ options || (options = {}); if (options.title) { this.albumName = options.title; }; $.ajax({ type: "GET", url: this.url, data: "album=" + this.albumName, dataType: "json", success: function(data){ console.log(data); loadPhotos(data); // <<< the problem is right here }, error: function(jqXHR, textStatus, errorThrown){ console.log("FETCH FAILED: " + errorThrown); } }); }, loadPhotos: function(filenames){ for (var i = 0; i < filenames.length; i++ ){ var photo = new Photo( {fileurl: filenames[i] }); var photoView = new PhotoView( { model: photo} ); this.add(photo); } } }); ```

Original source