【发布时间】:2012-03-11 21:02:56
【问题描述】:
我将如何等待多个商店加载?我有一个案例,只有在加载两个不同的商店时才需要做一些工作,所以使用一个商店的store.on("load", fn) 是不够的。
【问题讨论】:
标签: javascript extjs extjs4 store
我将如何等待多个商店加载?我有一个案例,只有在加载两个不同的商店时才需要做一些工作,所以使用一个商店的store.on("load", fn) 是不够的。
【问题讨论】:
标签: javascript extjs extjs4 store
我使用连锁装载商店来解决这个问题。
缺点:比应有的速度慢。
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);
【讨论】:
当有几家商店需要等待时,我们会使用它:
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'
);
}});
要使用它,请传入相关 storeIds 的数组:
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 或更高版本。
【讨论】:
通常我会避免这个问题,因为我努力尽量减少客户端/服务器往返并提高性能: 我在商店中将 autoLoad 设置为 false,然后执行显式 ajax 请求,一次获取所有商店的数据,然后使用 store.loadData() 直接将其设置到每个商店。 缺点当然是它需要更多的代码并导致更紧密的耦合。
【讨论】:
我有一些项目需要在处理数据之前加载多个商店。我在它们上添加了一个回调,以检查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。无论如何都应该有评论,以帮助我们所有人:)
我认为您可以为两个商店添加负载侦听器,并检查另一个是否完成...
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);
我认为这种方式只有在它们都被加载时才会调用该方法,前提是您知道两者都已发出加载请求。
【讨论】: