如何在每个循环中等待获取

How to wait fetch in each-loop

我希望每个项目都从服务器获取数据,然后创建一个包含这些数据的组合框。现在发生的事情是我得到了 3 个具有相同数据的组合框。

我有这个代码:

self.CollectionTest.each(function(item, index) {
    if (item.attributes.QuesAnswerType == 7) {
        self.dtype = item.attributes.QuesAnswerValue_Para;
        self.dropdowncollection = new QuestionaireDetailsCollection;
        self.dropdowncollection.fetch({
            reset: true,
            url: 'api/Variables/getPara',
            data: $.param({ type: self.dtype }),
            success: function() {
                self.dropdowndataSource = new kendo.Backbone.DataSource({
                    collection: self.dropdowncollection,
                });

                var cbid = "cb" + item.attributes.Id;
                $('<input id="' + cbid + '" dataTextField: "Name" dataValueField: "Id" data-bind="value:QuesDetAnswer"/>')
                    .appendTo("#divrb" + item.attributes.Id)
                    .kendoDropDownList({
                        dataTextField: "Name",
                        dataValueField: "Id",
                        dataSource: self.dropdowndataSource,
                        autoBind: true,

                    });
            } // end of success
        });

对我来说,问题似乎在于您总是为 self 对象赋值。 成功方法的代码是异步执行的。 因此,self 对象的值在每次成功的方法调用中都会被覆盖。

我建议尝试去掉成功方法中的 self 引用。像

var dropdowncollection = new QuestionaireDetailsCollection;
dropdowncollection.fetch({reset: true, url: 'api/Variables/getPara', data: $.param({ type: self.dtype }), success: function () {
    var dropdowndataSource = new kendo.Backbone.DataSource({
        collection: self.dropdowncollection,
    });

    var cbid = "cb" + item.attributes.Id;
    $('<input id="' + cbid + '" dataTextField: "Name" dataValueField: "Id" data-bind="value:QuesDetAnswer"/>')
    .appendTo("#divrb" + item.attributes.Id)
    .kendoDropDownList({
        dataTextField: "Name",
        dataValueField: "Id",
        dataSource: dropdowndataSource,
        autoBind: true,
    });
}

您处理问题的方式不对。您没有按应有的方式使用所有 Backbone,而是尝试 hard-code 回调中的所有内容。这是callback hell

您要做的是渲染 collection。在 Stack Overflow 上有很多关于渲染 list/collection 的问题,这里是我自己的一些答案,以列表渲染为例:

我将尝试演示如何在渲染之前获取每个。

将 url 放在它所属的位置,放入 collection class。

var QuestionaireDetailsCollection = Backbone.Collection.extend({
    url: 'api/Variables/getPara',
});

将项目呈现逻辑包装到视图中

var ItemView = Backbone.View.extend({
    template: _.template('<input id="cb<%= Id %>" dataTextField="Name" dataValueField="Id" data-bind="value:QuesDetAnswer"/>'),
    id: function() {
        return "divrb" + this.model.id;
    },
    initialize: function() {
        // let the item view handle the collection
        this.collection = new QuestionaireDetailsCollection();

        this.listenTo(this.collection, 'sync', this.onSync);

        this.collection.fetch({
            reset: true,
            data: $.param({ type: this.model.get('QuesAnswerValue_Para') }),
        });
    },
    render: function() {
        this.$input = $(this.template({ Id: this.model.id }))
        this.$el.html(this.$input);

        this.$input.kendoDropDownList({
            dataTextField: "Name",
            dataValueField: "Id",
            dataSource: this.dropdowndataSource,
            autoBind: true,
        });
        return this;
    },
    onSync: function() {
        this.dropdowndataSource = new kendo.Backbone.DataSource({
            collection: this.collection,
        });

        this.render();
    },
});

也将列表渲染包裹在视图中

var ListView = Backbone.View.extend({
    initialize: function() {
        this.childViews = [];
        this.quesAnswerType = 7;
        this.listenTo(this.collection, 'sync', this.render);
    },
    render: function() {
        this.$el.empty();

        // filter the models before rendering
        _.each(this.collection
            .where({ 
                QuesAnswerType: this.quesAnswerType
            }), this.renderItem, this);
        return this;
    },
    renderItem: function(model) {
        var view = new ItemView({ model: model });
        this.childViews.push(view);
        this.$el.append(view.render().el);
    },

    cleanup: function() {
        // avoid memory leaks
        _.invoke(this.childViews, 'remove');
        this.childViews = [];
    }
});