Backbone.js Просмотр с несколькими коллекциями и сортировкой
У меня есть представление с несколькими коллекциями, реализованными так:
collection: {
folders: new FolderCollection(),
images: new ImageCollection(),
files: new FileCollection()
},
И пример коллекции выглядит так:
var FolderCollection = Backbone.Collection.extend({
model: folderObj,
initialize:function (){
// this.bindAll(this);
// this.setElement(this.at(0));
},
comparator: function(model) {
return model.get("id");
},
getElement: function() {
return this.currentElement;
},
setElement: function(model) {
this.currentElement = model;
},
next: function (){
this.setElement(this.at(this.indexOf(this.getElement()) + 1));
return this;
},
prev: function() {
this.setElement(this.at(this.indexOf(this.getElement()) - 1));
return this;
}
});
Как вы можете себе представить, это представление представляет собой отображение файлов, изображений и папок. Затем я заполняю представление, вызывая три разные функции; один для заполнения представления папками, другой для файлов и другой для изображений. Каждая из этих функций представляет собой отдельный запрос AJAX. Таким образом, поскольку эти вызовы асинхронны, нет возможности сначала загрузить папки, затем изображения, затем файлы, и при загрузке страницы отсутствует согласованность.
Итак, моя проблема в том, что мне нужно иметь возможность заказать эти три коллекции несколькими способами. Первая проблема заключается в том, что вызовы асинхронные, иногда сначала загружаются папки, или, может быть, файлы и т. Д. Я могу придумать два способа исправить это:
Вызывайте следующую функцию только после завершения предыдущей. Это лучший способ? Если да, то как мне это сделать?
После загрузки всех коллекций отсортируйте их. Если да, то как лучше сортировать и упорядочивать несколько коллекций?
Если требуется больше кода (например, модель или представление), пожалуйста, дайте мне знать, и я могу предоставить то, что когда-либо понадобится.
спасибо Джейсон
РЕДАКТИРОВАТЬ - ПОКАЗЫВАЯ ВИД
var FileManagementView = TemplateView.extend({
viewName: 'fileManagement',
className: 'fileManagement',
events: {
//my events
},
collection: {
folders: new FolderCollection(),
images: new ImageCollection(),
files: new FileCollection()
},
//life cycle
initialize: function (options) {
TemplateView.prototype.initialize.apply(this, [options]);
},
templateContext: function (renderOptions) {
},
postRender: function () {
//more functions to set up the view
this.repopulateViewWithFoldersAndFiles(currentFolderId);
},
template: function (renderOptions) {
return 'MyMainTemplate';
},
repopulateViewWithFoldersAndFiles: function(currentFolderId){
//code to do stuff to create view
//these functions are all async, so theres no way to know what will finish first
this.getFolders(currentFolderId);
this.getImages();
this.getFiles();
},
getFiles: function(){
try{
var that = this;
var url = '?q=url to function';
$.ajax({
url: url,
context: that,
data:{'methodName': 'getFiles'}
}).done(function(data) {
var results = jQuery.parseJSON(data.result.results);
if(results){
$.each(results, function( key, value ) {
var file = new fileObj;
file.set('id', value.id);
file.set('fileName', value.fileName);
//...set more attributes
that.collection.files.add(file);
that.renderFile(file);
});
}
});
} catch(e){
throw e;
}
},
renderFile: function(file){
try{
if(file) {
var template = window.app.getTemplate('AnotherTemplate');
var html = $(template({
id: file.get('id'),
fileName: file.get('fileName'),
fileIconPath: file.get('fileIconPath')
}));
this.$el.find('#fileDropZone').append(html);
}
} catch(e){
throw e;
}
},
getImages: function(){
try{
var url = '?q=url to function';
$.ajax({
url: url,
context: that,
data:{'methodName': 'getImages'}
}).done(function(data) {
var results = jQuery.parseJSON(data.result.results);
if(results){
$.each(results, function( key, value ) {
var image = new imageObj;
image.set('id', value.id);
image.set('imgTitle', value.image_name);
//....set more attributes
that.collection.images.add(image);
that.renderImage(image);
});
}
});
} catch(e){
throw e;
}
},
renderImage: function(image){
try{
if(image) {
var template = window.app.getTemplate('myViewTemplate');
var html = $(template({
imgId: image.get('id'),
imgTitle: image.get('imgTitle'),
//..more attributes
}));
this.$el.find('#fileDropZone').append(html);
}
} catch(e){
throw e;
}
},
getFolders:function(parentId){
var that = this;
var url = '?q=...path to function';
$.ajax({
url: url,
context: that,
data:{'methodName': 'getFolders'}
}).done(function(data) {
var results = jQuery.parseJSON(data.result.results);
if(results){
$.each(results, function( key, value ) {
var folder = new folderObj();
folder.set('folderName', value.folder_name);
folder.set('id', value.folder_id);
//more attributes
that.collection.folders.add(folder);
that.renderFolders(folder);
});
}else{
this.renderFolders(null);
}
});
},
//renders the folders to the view
renderFolders: function(folder){
try{
if(folder) {
var template = window.app.getTemplate('myFolderTemplate');
var html = $(template({
folderId: folder.get('id'),
folderName: folder.get('folderName'),
}));
this.$el.find('#fileDropZone').append(html);
}
} catch(e){
throw e;
}
}
});
1 ответ
В итоге я переписал свои модели и создал одну модель, от которой унаследовали другие. Пример:
var DataModel =MyBaseModel.extend({
defaults: {
id: null,
//other shared fields
}
});
Все остальные мои модели унаследованы, вот так:
var folderObj = DataModel.extend({
// Whatever you want in here
urlRoot: '?q=myApp/api/myClassName/',
defaults: {
//other fields here
},
validate: function(attributes){
//validation here
}
});
Затем я использовал deferred, на который я ответил здесь: Jquery Promise и Defered с возвращенными результатами