Как мне дождаться загрузки нескольких магазинов? У меня есть случай, когда мне нужно выполнить некоторую работу только при загрузке двух разных хранилищ, поэтому с помощью store.on("load", fn)
одного магазина недостаточно хорош.
ExtJS ожидает загрузки нескольких магазинов
Ответы (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 или более поздняя версия.
У меня были проекты, которые требовали загрузки нескольких хранилищ перед работой с данными. Я добавил к ним обратный вызов, чтобы проверить, загружен ли каждый элемент в 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
}
}
loaded = !store.isLoading();
, который должен быть loaded &= !store.isLoading();
. См. этот jsfiddle. В любом случае должен быть комментарий, чтобы помочь нам всем :)
- person aletzo; 06.09.2012
Обычно я избегаю этой проблемы, потому что стремлюсь свести к минимуму обмен данными между клиентом и сервером и повысить производительность: я устанавливаю autoLoad в хранилище в false, затем делаю явный запрос ajax, который получает данные для всех хранилищ одновременно, затем использую store.loadData() чтобы напрямую установить его для каждого магазина. Недостатком, конечно же, является то, что для этого требуется больше кода и в результате получается более тесная связь.
я думаю, вы можете добавить прослушиватели загрузки для обоих хранилищ и проверить, закончился ли другой...
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);
Я думаю, что таким образом он будет вызывать метод только тогда, когда они оба загружены, предполагая, что вы знаете, что запрос на загрузку был сделан для обоих.
Я использую сетевые загрузочные магазины, чтобы решить эту проблему.
Минусы: медленнее, чем должно быть.
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);