如何在ExtJs中等待所有存储加载完成?

32

我有一组由五个存储驱动的组合框,我希望在所有存储都完全加载后触发一个函数。应该如何推荐实现?可能可以像这样做但感觉不太优雅:

var store1Loaded = false;
var store2Loaded = false;

store1.on('load', function(){
    store1Loaded = true;
});

store2.on('load', function(){
    store1Loaded = true;
});


store1.load();
store2.load();

function WaitForFunction()
{
    if (!store1Loaded || !store2Loaded)) {
       setTimeout( WaitForFunction, 100);
       return;
    }
    AllStoresLoaded();
}

function AllStoresLoaded(){
      //Do Something
}
7个回答

26

使用store.isLoading()方法,我认为它就是为此而设计的。我使用它,它运行得很好。

  1. 配置你想在执行某些逻辑之前加载的存储(使用storeId配置)。

  2. 将这些storeId放入数组中。

  3. 每当其中一个存储已加载时,迭代该数组,使用Ext.getStore查找存储并调用其上的isLoading方法。

  4. 如果数组中没有任何存储仍在加载,则执行您的逻辑。

例如,假设我想在执行某些逻辑之前加载store1store2(我以非MVC模式显示此示例,因为根据您的片段看起来您没有使用MVC模式)。

var store1 = Ext.create('Ext.data.Store', {
    model: myModel,
    storeId: 'store1', // store needs to be done MVC style or have this config
    proxy: {
        type: 'ajax', 
        url: 'url...',
        reader: 'json'
    },
    autoLoad: {
        callback: initData // do this function when it loads
    }
});

var store2 = Ext.create('Ext.data.Store', {
    model: myModel,
    storeId: 'store2',
    proxy: {
        type: 'ajax', 
        url: 'url...',
        reader: 'json'
    },
    autoLoad: {
        callback: initData // do this function when it loads
    }
});

// the stores to be checked
var myComboStores = ['store1', 'store2']

// function does logic if they are both finished loading
function initData() {
    var loaded = true;
    Ext.each(myComboStores, function(storeId) {
        var store = Ext.getStore(storeId);
        if (store.isLoading()) {
            loaded = false;
        }
    });
    if(loaded) {
        // do stuff with the data
    }
}

当存储未加载时,isLoading()是否等于false?这可能会成为一个问题吗? - o_nix
@o_nix你所说的“not loaded”是指“没有记录”吗?根据我的经验,isLoading只在请求和服务器响应之间的时间段内等于true。因此,如果服务器未返回任何记录,则仍将为true。这对我来说从未是问题。对我来说,它的主要作用是知道请求何时返回。如果要处理没有结果的响应,则可以实现不同的逻辑。 - egerardus
1
为了保持检查,也许可以使用setTimeout(me.initData,500)。 - VAAA
@VAAA 这样做的重点不是要使用计时器进行反复检查,而是因为它在“load”配置中,所以每当其中一个存储完成加载时,就会调用initData。当它被调用时,它会检查所有其他存储是否已经完成加载,如果是,则执行所需的任何逻辑。 - egerardus

8

使用超时并不是一个很好的解决方案,但完全依赖存储管理器也不是很好。

我会采取这样的做法:

var allStores = [store1, store2],
    len = allStores.length,
    loadedStores = 0,
    i = 0;

for (; i < len; ++i) {
    allStores[i].on('load', check, null, {single: true});
}

function check() {
    if (++loadedStores === len) {
        AllStoresLoaded();
    }
}

function AllStoresLoaded() {
    //Do Something
}

如果您经常使用它,甚至可以将其转换为类。

2
将此文本翻译成中文:
扩展存储 - 在子类中添加'loaded'属性,覆盖'initComponent()'并在其中附加到'load'事件,然后在事件处理程序中将'loaded'设置为true,添加'returning value of the 'loaded' property'的'isLoaded()'方法。
如果使用http传输,则可以使用store.proxy.conn.isLoading()。
请查看this

2
如果您遇到了下拉框在存储加载时间过长时无法正确显示/刷新的问题,解决方法是像这样创建每个要在下拉框中使用的存储:
Ext.create("Ext.data.Store", {
    ...,
    loading: true,
    ...
});

组合框检查它们使用的存储中的参数以在加载完信息后刷新信息,但有时组合框在存储开始加载且“loading”标志设置为true之前就被创建和刷新了,然后当存储完成加载时就不会刷新其值。 显式将其设置为true可以解决此问题。 我不知道这是否适用于您的情况,但我想提一下以防万一。


我们遇到了同样的问题,因为我们的ViewModel被返回为async Task<ActionResult>(Asp.Net MVC),而组合框在其存储加载之前尝试设置其值。将loading:true设置绝对解决了这个问题。 - mdisibio
这节省了我大量的时间/代码。我们有相同的combobox存储“race”条件,即在combobox加载其存储之前发生表单绑定。我找到了这个线程,以为我将不得不编写客户代码来等待所有存储加载完成,然后才能继续进行我的form.loadRecord操作。这个简单的存储配置解决了问题。非常感谢! - Wade Bee

2
function storeLoadingHandler(justLoadedStore) {
    // I use some quick hacky flag, you can do it by your own way
    justLoadedStore.loaded = true;

    var allStoresLoaded = true;

    // just walk through all stores registered in the application
    // do not forget to use MVC-style stores or add 'storeId' manually
    // or register every store with your custom code
    Ext.StoreManager.each(function(existingStore) {
        // we have to ignore system stores
        if (existingStore.storeId != 'ext-empty-store') {
            if (!existingStore.loaded) { // our flag or undefined
                // nope, at least one of stores is not loaded
                allStoresLoaded = false;

                return false
            }
        }
    })

    if (allStoresLoaded) // then do something
        alert('All stores are loaded.');
}

// add the loading handler for all stores
Ext.StoreManager.each(function() {
    this.on('load', storeLoadingHandler);
})

1

ExtJs的Store有一个方法load,load方法有回调函数。

我已经创建了一个演示,你可以在这里查看Sencha fiddle

这个函数将创建并返回一个store。

function createStore(id) {
    return Ext.create('Ext.data.Store', {
        storeId: 'store_' + id,
        alias: 'store.store_' + id,
        proxy: {
            type: 'ajax',
            url: 'data.json',
            timeout: 300000,
            reader: {
                type: 'json',
                rootProperty: 'data'
            }
        }
    });
}

例如,我有一个存储数组。它包含storeId或别名。
var storeArry = [],
    store = '';

for (var key = 0; key < 5; key++) {
    storeArry.push(createStore(key).storeId);
}

在每个存储回调函数中,我们可以从storeArray中删除数据或维护一个变量进行检查。
Ext.getBody().mask('Please wait..');
Ext.defer(function () {
    Ext.getBody().unmask();
    Ext.Array.forEach(storeArry, function (storeId) {
        //For checking store is created or not
        //if store is not created we can create dyanamically using passing storeId/alias
        store = Ext.getStore(storeId);
        if (Ext.isDefined(store) == false) {
            store = Ext.create(storeId);
        }
        store.load({
            callback: function () {
                //On every store call back we can remove data from storeArray or maintain a veribale for checking.
                Ext.Array.remove(storeArry, this.storeId);
                if (storeArry.length == 0) {
                    Ext.Msg.alert('Success', 'All stored is loaded..!');
                }
            }
        });
    });
}, 3000);

1

使用 Deft JS

Deft JS 是通过依赖注入注入的附加组件。它允许用户在 AJAX 调用中添加 promises,并且只有当调用完成时才会解决 promise。Deft JS 的链接。 使用 Ext.defer.All(); 来加载所有 5 个存储库,一旦所有存储库都加载完成,将调用特定的回调函数。在该函数中,实现您的逻辑。


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