32

I have a set of combo boxes that are driven by five stores and I want to fire a function once all the stores are completely loaded. What is the recommended way of doing this? I could do something like this but it feels kludgy:

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
}
4

7 回答 7

25

Use the store.isLoading() method, I think that is what it is for. I use it and it works fine.

  1. Configure the stores that you want to be loaded before performing some logic with a storeId config.

  2. Put these storeIds into an array.

  3. Whenever one of these stores is loaded iterate through the array, lookup the store with Ext.getStore and call isLoading on it.

  4. If none of the stores in the array are still loading, perform your logic.

For example, say I want store1 and store2 loaded before I perform some logic (I am showing this in non-MVC pattern because it looks like you are not using MVC pattern from your snippet).

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
    }
}
于 2012-06-13T00:11:16.367 回答
8

Using timeouts isn't a great solution, however also having to rely on everything in the store manager isn't great either.

I'd do something like:

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
}

If you're using it alot you could even turn it into a class.

于 2012-06-12T22:10:40.197 回答
2

Extend the store - add the 'loaded' property to the child class, override 'initComponent()' and attach to 'load' event inside it, raise the 'loaded' to true inside the event handler, add the 'isLoaded()' method returning value of the 'loaded' property.

Other way, if you use http transport - store.proxy.conn.isLoading()

Take a look at this

于 2012-06-12T19:40:33.790 回答
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);
})
于 2012-06-12T20:37:58.113 回答
2

If you have a problem because the combobox are not displayed/refreshed properly when the stores take too long to load, the solution is to create every store which is to be used in a combobox like this

Ext.create("Ext.data.Store", {
    ...,
    loading: true,
    ...
});

Comboboxes check that parameter in the stores they use to refresh the info once it's loaded, but sometimes the combobox is created and refreshed even before the store starts to load and the 'loading' flag is set to true, and then it won't refresh its value when the store finishes loading. Setting it to true explicitly fixes the issue. I don't know if that is your case, but I thought I would mention it in case it is.

于 2014-01-17T11:03:16.547 回答
1

Use Deft JS

Deft JS is a addon injected via dependancy injection. It allows user to add promises in AJAX calls and the promise is resolved only when the call is done. Link for Deft JS. Use Ext.defer.All(); to load all your 5 stores and a particular callback function will be called once all the stores are loaded. In that function, Implement your logic.

于 2016-03-27T15:20:38.223 回答
1

ExtJs Store have method load and load method have callback function.

I have created a demo. you can check here Sencha fiddle

This function will create store and return.

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

For Example I have array of store. It contain storeId or alias.

var storeArry = [],
    store = '';

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

On every store callback we can remove data from storeArray or maintain a variable for checking.

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);
于 2017-09-20T07:32:53.013 回答