Backbone.js View с несколькими коллекциями и сортировкой

У меня есть представление с несколькими коллекциями, реализованными следующим образом:

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 должен реагировать на обновление модели/коллекции. Вам лучше делать звонки вне вашего представления.   -  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 и Deferred с возвращенными результатами< /а>

person jason    schedule 24.01.2016