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;
        }
    }   
});

person jason    schedule 28.09.2015    source източник
comment
Опитахте ли обещания?   -  person Lesha Ogonkov    schedule 29.09.2015
comment
Можете ли да покажете и вашето виждане?   -  person antejan    schedule 29.09.2015
comment
Леша, не съм сигурен какво имаш предвид под обещания? antejan, да, ще добавя съкратена версия на моя изглед.   -  person jason    schedule 30.09.2015
comment
Определено трябва да погледнете Обещания. Освен това избирате грешен начин, когато се уморите да правите повиквания от View, View трябва да отговори на актуализация на модел/колекция. По-добре провеждайте разговорите си извън своя View.   -  person Lesha Ogonkov    schedule 30.09.2015


Отговори (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 с върнати резултати

person jason    schedule 24.01.2016