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.
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.