如何在ExtJs中等待所有的存储同步?

6
我有一个网格列表,可以由最终用户以表单的形式更改其数据。 最后,我想通过点击按钮同步所有网格,然后执行操作。
我编写了以下代码:
$.when.apply(
    Ext.ComponentQuery.query('grid')
       .forEach(function(item) {
             if (item.getXType() == "grid") {
                if (item.store.getNewRecords().length > 0 || item.store.getUpdatedRecords().length > 0 || item.store.getRemovedRecords().length > 0) {
                    item.store.sync();
                 }
             }
})).then(function (results) {
    //do something
});

问题在于store.sync()没有等待回调函数。

推荐的方法是什么?


应该不需要使用 store.sync(),可以直接使用配置项 autoSync: true - Martin Zeitler
@MartinZeitler 我的网格中有很多数据,不想为每个单元格编辑发送请求。 - Hossein
它只会同步已更改的一行 - 因为用户一次不会更改多行 - 这几乎不会增加更多的流量,只是分成更多的请求。在现今时代,人们往往在家中拥有> 100mbit / s的网络速度。 - Martin Zeitler
@MartinZeitler 我用 Promise 来实现,不管怎样,谢谢。 - Hossein
@MartinZeitler autoSync 改变了程序的行为。不确定为什么你会推荐这个。你想让 Excel 在不询问的情况下自动保存所有更改吗? - Alexander
2个回答

5
我使用 Promise 来实现这个功能:
 // Sync grid data if exist dirty data
 Promise.all(
     Ext.ComponentQuery.query('grid')
     .map(grid => grid.getStore())
     .filter(s => (s.getNewRecords().length + s.getUpdatedRecords().length + s.getRemovedRecords().length) > 0)
     .map(s => new Promise((resolve, reject) => {
           s.sync({
               success: () => { resolve(); },
               failure: () => { reject(); }
           });
      }))
      ).then(() => {
           //do something
      });

如何等待所有 ExtJs 存储同步完成?我有一个需要在所有存储同步完成后执行的函数。 我该如何等待所有存储同步完成?我已经尝试了以下代码,但它不起作用:Ext.getStore('store1').on('load', function() { Ext.getStore('store2').on('load', function() { // All stores are loaded }); });这个问题很棘手,因为我不知道有多少个存储需要同步。 - Evan Trimboli
@EvanTrimboli :( 是的,我也在那里问过这个问题。 - Hossein
只是一些归属。 - Evan Trimboli

2
您可以在您的 store.sync() 方法中使用 callback

callback 函数会在同步完成后被调用。无论成功或失败,回调函数都会被调用,并传递以下参数:(batch, options)。

您可以按照以下方式实现您的要求:

  1. 在循环之前创建一个空数组,如 var gridIds=[]

  2. 在循环内,在调用 store.sync() 之前将 grid id 推入上述数组中。

  3. 现在在 callback 函数中从上述数组中删除该 grid id 并检查条件数组是否为空,如果为空则说明您所有的存储同步响应已到达。

您可以在这里查看工作的Fiddle

注意 我使用了虚拟 API,请使用您的实际 API。

代码片段

Ext.application({
    name: 'Fiddle',

    launch: function () {

        Ext.define('MyStore', {
            extend: 'Ext.data.Store',

            alias: 'store.mystore',

            fields: ['name'],

            autoLoad: true,

            pageSize: 25,

            remoteSort: true,

            proxy: {
                type: 'ajax',
                method: 'POST',
                api: {
                    read: 'data.json',
                    update: 'your_update_api',
                    create: 'your_create_api',
                    destroy: 'your_delete_api'
                },
                reader: {
                    type: 'json'
                },
                writer: {
                    type: 'json',
                    encode: true,
                    root: 'data'
                }
            },
        });

        Ext.define('MyGrid', {

            extend: 'Ext.grid.Panel',

            alias: 'widget.mygrid',

            store: {
                type: 'mystore'
            },

            height: 200,

            border: true,

            tools: [{
                xtype: 'button',
                iconCls: 'fa fa-plus-circle',
                tooltip: 'Add New Record',
                handler: function () {
                    let grid = this.up('grid'),
                        store = grid.getStore();

                    store.insert(0, {
                        name: 'Test ' + (store.getCount() + 1)
                    });
                }
            }],
            columns: [{
                text: 'Name',
                dataIndex: 'name',
                flex: 1
            }]
        });

        Ext.create({
            xtype: 'panel',
            // title: 'Store sync example',

            items: [{
                xtype: 'mygrid',
                title: 'Grid 1'
            }, {
                xtype: 'mygrid',
                title: 'Grid 2'
            }, {
                xtype: 'mygrid',
                title: 'Grid 3'
            }, {
                xtype: 'mygrid',
                title: 'Grid 4'
            }],

            bbar: ['->', {
                text: 'Submit Changes',
                handler: function (btn) {
                    var panel = btn.up('panel'),
                        grids = panel.query('grid'),
                        gtidIds = [],
                        lenthCheck = function (arr) {
                            return arr.length > 0;
                        };

                    grids.forEach(function (grid) {
                        let store = grid.getStore();
                        if (lenthCheck(store.getNewRecords()) || lenthCheck(store.getUpdatedRecords()) || lenthCheck(store.getRemovedRecords())) {
                            panel.mask('Please wait...');
                            gtidIds.push(grid.getId());
                            store.sync({
                                callback: function () {
                                    Ext.Array.remove(gtidIds, grid.getId());
                                    if (gtidIds.length == 0) {
                                        panel.unmask();
                                        Ext.Msg.alert('Info', 'All grid store sync success.');
                                    }
                                }
                            }, grid);
                        }
                    });
                }
            }],
            renderTo: Ext.getBody(),
        })
    }
});

感谢您的回答,但这不是我想要的,因为我需要在所有“grid.store.sync()”之后执行一些操作。 - Hossein
是的,你可以在 store.sync 之后进行管理。我认为应该通过 fiddle 调试代码。因为在回调函数中,我已经检查了条件,如果所有的 store.sync 响应都到达了,那么我们就可以放置我们想要的逻辑。 - Narendra Jadhav
没错,谢谢你,但我认为Promise更好,不是吗? - Hossein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接