ExtJS ожидает загрузки нескольких магазинов

Как мне дождаться загрузки нескольких магазинов? У меня есть случай, когда мне нужно выполнить некоторую работу только при загрузке двух разных хранилищ, поэтому с помощью store.on("load", fn) одного магазина недостаточно хорош.


person Alex Ivasyuv    schedule 21.02.2012    source источник
comment
Связано с stackoverflow.com/questions/11003605/   -  person Patrick    schedule 29.10.2012


Ответы (5)


Мы используем это, когда есть несколько магазинов для ожидания:

Ext.define('Ext.ux.StoreLoadCoordinator', {
mixins: {
    observable: 'Ext.util.Observable'
},
resetStoreLoadStates: function() {
    this.storeLoadStates = {};              

    Ext.each(this.stores, function(storeId) {
        this.storeLoadStates[storeId] = false;
    }, this);       
},    
isLoadingComplete: function() {
    for (var i=0; i<this.stores.length; i++) {
        var key = this.stores[i];

        if (this.storeLoadStates[key]==false) {
            return false;
        }
    }

    return true;        
},    
onStoreLoad: function(store, records, successful, eOpts, storeName) {
    this.storeLoadStates[store.storeId] = true;

    if (this.isLoadingComplete()==true) {
        this.fireEvent('load');
        this.resetStoreLoadStates();
    }
},    
constructor: function (config) {
    this.mixins.observable.constructor.call(this, config);

    this.resetStoreLoadStates();

    Ext.each(this.stores, function(storeId) {
        var store = Ext.StoreManager.lookup(storeId);

        store.on('load', Ext.bind(this.onStoreLoad, this, [storeId], true));
    }, this);

    this.addEvents(
        'load'            
    );
}});

Чтобы использовать его, передайте массив соответствующих storeId:

var store1 =  Ext.create('Ext.data.Store', {
    storeId: 'Store1',
    .... (rest of store config)
}});        

var store2 =  Ext.create('Ext.data.Store', {
    storeId: 'Store2',
    .... (rest of store config)
}});        


var coordinatior = Ext.create('Ext.ux.StoreLoadCoordinator', {
    stores: ['Store1', 'Store2'],
    listeners: {
        load: function() {
           // Do post-load work
        }
    }
});         

Это даст вам одно событие загрузки для обработки нескольких магазинов. Обратите внимание, что для этого требуется Ext 4.x или более поздняя версия.

person McCroskey    schedule 28.07.2013
comment
Превосходно! Спасибо - person Black; 03.02.2014

У меня были проекты, которые требовали загрузки нескольких хранилищ перед работой с данными. Я добавил к ним обратный вызов, чтобы проверить, загружен ли каждый элемент в Ext.data.StoreManager, и если да, то он будет делать с данными то, что мне нужно.

Чтобы добавить магазины в StoreManager, вам просто нужно указать storeId в его конфигурации, что-то вроде этого:

var store1 = Ext.create('Ext.data.Store', {
    model: myModel,
    storeId: 'store1', //<-- adds this to Ext.data.StoreManager
    proxy: {
        type: 'ajax', 
        url: 'url...',
        reader: 'json'
    },
    autoLoad: {
        callback: initData
    }
});

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

// Initialize store dependencies when all stores are loaded
function initData() {
    var loaded;
    Ext.data.StoreManager.each( function(store) {
        loaded = !store.isLoading();       
        return loaded;
    });
    if(loaded) {
        // do stuff with the data
    }
}
person egerardus    schedule 21.02.2012
comment
Не уверен, но я думаю, что минус был из-за loaded = !store.isLoading();, который должен быть loaded &= !store.isLoading();. См. этот jsfiddle. В любом случае должен быть комментарий, чтобы помочь нам всем :) - person aletzo; 06.09.2012

Обычно я избегаю этой проблемы, потому что стремлюсь свести к минимуму обмен данными между клиентом и сервером и повысить производительность: я устанавливаю autoLoad в хранилище в false, затем делаю явный запрос ajax, который получает данные для всех хранилищ одновременно, затем использую store.loadData() чтобы напрямую установить его для каждого магазина. Недостатком, конечно же, является то, что для этого требуется больше кода и в результате получается более тесная связь.

person Stephen Friedrich    schedule 22.02.2012

я думаю, вы можете добавить прослушиватели загрузки для обоих хранилищ и проверить, закончился ли другой...

this.getStore('store1').on('load',function(store){
   if (this.getStore('store2').isLoading() == false ){
     // callMethod to perform action ....
   }
},this);

this.getStore('store2').on('load',function(store){
   if (this.getStore('store1').isLoading() == false ){
      // callMethod to perform action....
   }
},this);

Я думаю, что таким образом он будет вызывать метод только тогда, когда они оба загружены, предполагая, что вы знаете, что запрос на загрузку был сделан для обоих.

person nscrob    schedule 21.02.2012

Я использую сетевые загрузочные магазины, чтобы решить эту проблему.

Минусы: медленнее, чем должно быть.

chainStoreLoad :function (stores, lastCall, idx)
{
    if (idx === stores.length) {
        if ("function" === typeof lastCall) {
            lastCall.call ();
        }
        return;
    }
    stores[idx].load (function (r,o,s) {
        Jx.chainStoreLoad (stores, lastCall, idx + 1);
    });
}

Пример:

Jx.chainStoreLoad (
    [
        this.storeAssetType
    ,   this.storeAssetProcurement
    ,   this.storeAssetStatus
    ,   this.storeAssetLocation
    ,   this.storeSystemUser
    ]
,   function ()
    {
        self.panel.doRefresh (perm);
    }
,   0);
person sulhan    schedule 23.05.2014