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. Таким образом, поскольку эти вызовы асинхронны, нет возможности сначала загрузить папки, затем изображения, затем файлы, и при загрузке страницы отсутствует согласованность.

Итак, моя проблема в том, что мне нужно иметь возможность заказать эти три коллекции несколькими способами. Первая проблема заключается в том, что вызовы асинхронные, иногда сначала загружаются папки, или, может быть, файлы и т. Д. Я могу придумать два способа исправить это:

  1. Вызывайте следующую функцию только после завершения предыдущей. Это лучший способ? Если да, то как мне это сделать?

  2. После загрузки всех коллекций отсортируйте их. Если да, то как лучше сортировать и упорядочивать несколько коллекций?

Если требуется больше кода (например, модель или представление), пожалуйста, дайте мне знать, и я могу предоставить то, что когда-либо понадобится.

спасибо Джейсон

РЕДАКТИРОВАТЬ - ПОКАЗЫВАЯ ВИД

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 с возвращенными результатами

Другие вопросы по тегам