Search code examples
javascriptjsonrestbackbone.js

Use Backbone fetch to retrieve list


I am new to Backbone.js and feel I must be missing something very basic. I am trying to understand how to set up a model/collection that can retrieve data. Toward that end, I'm instantiating a model/collection and then immediately calling fetch() to populate it (I know that bootstrapping the first call is best practice, but I just want to understand fetch() right now). The sample model I've created does initiate a network call to the RESTful service, but it remains in a Pending state after the fetch call, and my success callback in the fetch call is never reached, so the model never gets any data.

Here is my js code:

var MyProducts = Backbone.Collection.extend({
    url: contextPath + "/carousel.json"
});

var MyProductsCollection1 = Backbone.Collection.extend({
    urlRoot: contextPath + "/carousel.json",
    url: contextPath + "/carousel.json"
});

var MyProductsCollection2 = Backbone.Collection.extend({
    url: contextPath + "/carousel.json"
});

var MyView = Backbone.View.extend({

    render: function () {
        console.log('this.collection');
        console.log(this.collection);

        return this;
    }
})

var myProducts;
var myProductsCollection1;
var myProductsCollection2;

$(function () {
    myProducts = new MyProducts();
    myProducts.fetch({
        success: function (model) {
            var result = model.get("records");
        }
    });

    myProductsCollection1 = new MyProductsCollection1();
    myProductsCollection1.fetch({
        success: function (model) {
            var result = model.get("records");
        }
    });

    myProductsCollection2 = new MyProductsCollection2();
    myProductsCollection2.fetch({
        success: function (model) {
            var result = model.get("records");
        }
    });

    var myView1 = new MyView({ collection: myProductsCollection1 });
    var myView2 = new MyView({ collection: myProductsCollection2 });
    console.log('view1');
    myView1.render();
    console.log('view2');
    myView2.render();
});

Here is the console output, which seems to me to indicate that no records were retrieved from the fetch() calls:

view1
this.collection
child {length: 0, models: Array[0], _byId: Object}
view2
this.collection
hild {length: 0, models: Array[0], _byId: Object}

In the Network tab, there are 3 requests to carousel.json, but all show with Status = pending, indicating they did not complete.

The domain of the REST api is the same as that of the website (I'm calling Spring controllers for retrieving both views and this JSON), so there should not be any cross-domain issues).

Here are some of the results of a Postman call to https://mydomain/mycontextdir/carousel.json. (The actual result set is longer, but is formatted the same way):

{
    "records": [
        {
            "properties": [
                {
                    "name": "pDefaultCatgroupID",
                    "value": "1000357"
                },
                {
                    "name": "highPriceFormatted",
                    "value": "$7.95"
                },
                {
                    "name": "REG_HIGH_PRICE",
                    "value": "7.950000"
                }
            ]
        },
        {
            "properties": [
                {
                    "name": "REG_LOW_PRICE",
                    "value": "13.950000"
                },
                {
                    "name": "pItemID",
                    "value": "1254778"
                }
            ]
        }
     ],
    "navigableFacets": null,
    "refinmentFacets": null,
    "breadcrumbs": [],
    "content": null,
    "totalRecords": 5868,
    "navigationPath": [],
    "searchReport": {
        "fault": {
            "hasFault": false,
            "faultCommandName": null,
            "faultCode": null,
            "faultStatus": null,
            "faultMessageKey": null,
            "faultMessage": null,
            "errors": null
        },
        "commerceId": null,
        "loggedInCommerce": false,
        "terms": null,
        "autoSuggestion": null,
        "profanity": false
    }
}

What am I doing wrong that prevents the data from being retrieved?

Many thanks for your assistance!


Solution

  • It looks like your confusing the fetch from a Model for the fetch from a Collection (note the differences in the parameters passed to the success callback). When you call fetch on a collection the collection expects back an array of model data, if you data doesn't fit that format you can override it's parse function to handle the data. Being that your json is actually an object and not an array you will need to parse it yourself.

    So in your case what you want to do is

    var MyProducts = Backbone.Collection.extend({
        url: contextPath + "/carousel.json",
        parse: function (data) {
          return data.records;
        }
    });
    
    
    var myProducts = new MyProducts();
    myProducts .fetch({
      success: function (collection, response, options) {
        alert(collection.length);
      });
    

    Here's a link to a jsbin