backbone.jsmarionettebackbone.js-collections

Populating data from two different url in a backbone collection


I have a Marionette.LayoutView which calls a backbone collection and fetches the data and renders based on response. Now the issue that I am facing is, this collection needs to get data from two different endpoints, both should be independent, and then return the combined result. Below is my code:

My Marionette.LayoutView

var View = Marionette.LayoutView.extend({

    template: _.template(some.html),

    regions: {
        div1: '[data-region="div1"]',
        div2: '[data-region="div2"]',
    },

    initialize: function () {
        this.collection = new MovieCollection();
    },

    onRender: function () {
        if (this.collection.length) {
            this.div1.show(new TopMoviesByLikesView({
                collection: this.collection,
                movieCount: 10,
            }));

            this.div2.show(new TopMovieByRatingsView({
                collection: this.collection,
                movieCount: 10,
            }));
        }
    },

});

module.exports = AsyncView.extend({
    ViewConstructor: View,
});

My Collection

module.exports = Backbone.Collection.extend({

    model: TopMovieModel,

    initialize: function (response) {
        let movieCollection = [];
            let movieSourceOne = new TopMovieFromSourceOne();
            movieSourceOne.fetch({
                success: function (collection, response) {
                    movieCollection = [...movieCollection, ...response.data];
                },
                error: function (collection, response, options) {
                    console.info('~ Response::ERROR', collection, response, options);
                }
            });
        let movieSourceTwo = new movieSourceTwo();
        movieSourceTwo.fetch({
            success: function (collection, response, options) {
                movieCollection = [...movieCollection, ...response.data];
            },
            error: function(collection, response, options) {
                console.info('~ Response::ERROR', collection, response, options);
            }
        });
        this.collection = movieCollection;
    },

The error I get is A “url” property or function must be specified is there a way where I can do this without using a url in backbone collection? Note: I want to keep two endpoints independent since I don't want the collection to fail if primary API fails.


Solution

  • To avoid that error with url, you should override your fetch method, to call both collections fetch instead.

    function promisifyFetch(collection) {
      return new Promise(function(resolve, reject) {
        collection.fetch({
          success() {
            resolve(collection);
          },
    
          error() {
            reject();
          }
        });
      });
    }
    
    module.exports = Backbone.Collection.extend({
      model: TopMovieModel,
    
      initialize() {
        this.movieSourceOne = new TopMovieFromSourceOne();
        this.movieSourceTwo = new movieSourceTwo();
      },
    
      fetch(options) {
        return Promise.all([
          promisifyFetch(this.movieSourceOne),
          promisifyFetch(this.movieSourceTwo)
        ]).then(([one, two]) => {
          const response = [
            ...one.toJSON(),
            ...two.toJSON()
          ];
    
          this.set(response, options);
          this.trigger('sync', this, response, options);
        });
      }
    });
    

    You probably want to handle errors here aswell.