ExtJS和复杂的保存操作
ExtJS and Complex Save Operations
ExtJS 4.1.0
更新6/6/13:
我在Sencha论坛上发布了同样的问题,那里没有太多的行动。这篇文章或多或少是相同的,但我想我将在这里添加它只是供参考。我仍然渴望听到其他社区成员对ExtJS应用程序中非常常见的场景的输入!http://www.sencha.com/forum/showthread.php?265358-Complex-Model-Save-Decoupling-Data-and-Updating-Related-Stores
2013年7月16日更新(结论?)
Sencha的帖子几乎没有引起讨论。我决定将复杂保存操作的大部分负载放在应用程序服务器上,并在需要时惰性刷新客户端存储。通过这种方式,我可以使用自己的数据库包装器来包含与一个复杂域对象保存相关联的所有事务,以保证原子性。如果保存一个新的Order
包括保存订单元数据、10个新的OrderContents
实例和潜在的其他信息(驻留在其他表中的地址、在创建订单时定义的新客户等),我宁愿将有效负载发送到应用服务器,而不是在客户端应用程序代码中建立一个庸俗的回调网络。一对一关联的数据(如Order
hasOne Address
)在Order.save()
操作的success
回调中更新。更复杂的数据,比如Order
的内容,可以通过简单地调用contentStore.sync()
来惰性地处理。我觉得这是保证原子性而不需要大量客户端回调的方法
原创内容
考虑到保存大量关联模型的整体功能令人失望,我几乎放弃了应用程序中的模型关联,并依赖于自己检索相关数据。这一切都很好,但不幸的是并没有解决实际保存数据和更新ExtJS存储以反映服务器上的变化的问题。
以保存一个Order
对象为例,它由元数据和OrderContents
组成,即订单上的部件。元数据在数据库的Order_Data
表中结束,而内容在Order_Contents
表中结束,其中每一行都通过order_id
列链接到父订单。
在客户端,检索订单的内容非常容易,不需要任何关联:var contents = this.getContentsStore().query('order_id', 10).getRange()
。然而,一个主要的缺陷是这是依赖于OrderContents
ExtJS Store中可用的内容记录,如果我使用数据服务器与"main"对象不返回的关联,则适用。
在保存订单时,我发送一个请求,该请求包含订单的元数据(例如,日期、订单号、供应商信息等)以及一个内容数组。这些数据片段被拆分并保存到相应的表中。这对我来说很有意义,而且效果很好。
在从应用服务器返回保存/更新的记录之前,一切都很好。由于请求是通过调用OrderObject.save()
触发的,因此没有任何东西告诉OrderContents
存储有新记录可用。如果我将记录添加到存储并调用.sync()
,这将自动处理,但我觉得这会使保存过程复杂化,我宁愿在应用程序服务器上处理这种解耦,更不用说保存整个请求了。
有更好的方法来解决这个问题吗?我目前的解决方案如下……
var orderContentsStore = this.getOrderContentsStore();
MyOrderObject.save({
success: function(rec, op){
// New Content Records need to be added to the contents store!
orderContentsStore.add(rec.get('contents')); // Array of OrderContent Records
orderContentsStore.commitChanges(); // This is very important
}
});
通过调用commitChanges()
,添加到存储中的记录被认为是干净的(非幻影,非脏的),因此不再由存储的getModifiedRecords()
方法返回;因为在发生store.sync()
的情况下,记录不应该被传递到应用程序服务器。
这种方法对我来说似乎有点草率/粗糙,但我还没有找到更好的解决方案…
任何输入/想法都非常感谢!
Update 8/26/13我发现关联的数据确实是由Ext在模型代理的创建/更新回调中处理的,但发现数据并不容易…ExtJS 4.1 -在Model.Save()响应中返回关联数据
这个问题已经公开了几个月了,我觉得这个问题没有神奇的解决方案。
我的解决方案如下…
当保存一个复杂的模型(例如,一个模型,或者确实有一些hasMany
关联),我保存"父"模型,其中包括所有关联的数据(作为模型上的属性/字段!),然后在afterSave/afterUpdate回调中添加(保存的)关联数据。
以我的PurchaseOrder
模型为例,hasMany
Items
和hasOne
Address
。请注意,关联数据包含在模型的属性中,因为如果它只存在于模型的关联存储中,它将不会传递给服务器。
console.log(PurchaseOrder.getData());
---
id: 0
order_num: "PO12345"
order_total: 100.95
customer_id: 1
order_address: Object
id: 0
ship_address_1: "123 Awesome Street"
ship_address_2: "Suite B"
ship_city: "Gnarlyville"
ship_state: "Vermont"
ship_zip: "05401"
...etc...
contents: Array[2]
0: Object
id: 0
sku: "BR10831"
name: "Super Cool Shiny Thing"
quantity: 5
sold_price: 84.23
1: Object
id: 0
sku: "BR10311"
name: "Moderately Fun Paddle Ball"
quantity: 1
sold_price: 1.39
我已经为PurchaseOrder.Content
和PurchaseOrder.Address
建立了Models
,但PurchaseOrder
中的数据并不是这些模型的实例,而只是数据。同样,这是为了确保它被正确地传递给应用服务器。
.save()
将它发送到我的应用服务器,如下所示:
PurchaseOrder.save({
scope: me,
success: me.afterOrderSave,
failure: function(rec,op){
console.error('Error saving Purchase Order', op);
}
});
afterOrderSave: function(record, operation){
var me = this;
switch(operation.action){
case 'create':
/**
* Add the records to the appropriate stores.
* Since these records (from the server) have an id,
* they will not be marked as dirty nor as phantoms
*/
var savedRecord = operation.getResultSet().records[0]; // has associated!
me.getOrderStore().add(savedRecord);
me.getOrderContentStore().add(savedRecord.getContents()); //association!
me.getOrderAddressStore().add(savedRecord.getAddress()); // association!
break;
case 'update':
// Locate and update records with response from server
break;
}
}
我的应用程序服务器接收PurchaseOrder
并相应地处理保存数据。由于这个过程在很大程度上取决于您自己的实现,所以我不会详细介绍。我的应用程序框架松散地基于Zend 1.11(主要利用Zend_Db
)。
我觉得这是最好的方法,原因如下:
- 客户端没有乱七八糟的model.save()回调字符串
- 只有一个请求,非常容易管理
- 原子性很容易在应用服务器上处理
- 更少的往返=更少的潜在故障点需要担心
- 如果你真的很懒,回调的
success
方法可以简单地reload
存储。
为了鼓励讨论,我先把这个答案放一放。
感谢阅读!
- 我应该如何将响应数据保存在对象(json)中以获得更好的操作和性能
- 为主题选项(部分)创建一个ajax处理的保存操作
- 在web浏览器中保存操作过的SVG图像
- 如何在画布上绘制(使用鼠标/触摸)、保存绘制的对象、存储、加载和操作
- 从HTML表单中获取计算得到的JavaScript数据,并将其作为新元素添加到相同的表单操作中以使用PHP保存
- 防止对模式保存执行双重操作
- 在操作方法中保存图像,然后将 URL 返回给客户端
- 有没有一种方法可以保存JavaScriptDOM操作
- 取消操作后,我无法在geoserver中保存图层
- 将操作后的元素保存到mysql中
- 如果在按 jqgrid 中的保存操作按钮返回错误,如何保持内联添加
- SVG和Javascript代码是否可以保存在单独的文件中,并且仍然让脚本操作SVG元素
- 如何在JavaScript中保存未经授权的操作
- commandButton双重操作:保存并重定向到其他页面
- 是否可以将DOM操作保存在原始HTML文件中?
- ExtJS和复杂的保存操作
- 如何在Dynamics CRM 2013中保存操作失败时获取客户端错误详细信息
- 对HTML应用DOM操作并保存结果
- 使用Mongoose保存多个文档,并在保存最后一个文档时执行操作
- 在保存操作之前获取记录's指南