B/S开发者和HTML5的支持者和狂热粉丝的开篇宣言
期待HTML5和web应用能再次繁荣,移动互联网时代,我们不落伍!
还我们一个干净的手机,讨厌某应用整天获取联系人列表!
下完这个下那个,8G能放些什么?
介绍:
这写给使用Ember的前端工程师们,其实Ember很好实现预加载,
因为Ember的数据时由Ember Data提供的,只要提前把资源从后台加载到DS.store中,就能完全脱离后台运行。
问题的提出:
这个问题想了很久了,因为自己经常使用手机穿梭在地铁公交之上,无聊时会浏览一些手机应用获取一些感兴趣的信息。由于网络信号与建筑物等等诸多因素影响,导致网络很不稳定,绝大多数移动应用的使用感受十分不好,有些应用提示断线直接退出(andoird&IOS),在登陆恢复之前的页面甚至都不可以了,好一点的提示断线重连后可以继续。
那么能不能更进一步提升用户体验呢?让用户在断网后一段时间内仍然能够继续某些操作,因为绝大多数情况这段时间内网络又能恢复,这种设计就是使得用户对断网没有任何觉察。
答案
预加载是唯一的答案,预加载些什么呢?无非是程序和资源
1,一次性加载所有的js程序。这些js程序经过压缩,体积比较小,使一次加载成为可能。
2,资源,一定是不能全部加载的,要找出用户在接下来一段时间最有可能访问的资源,只加载这些资源。
如何实现预加载
第一点,很容易做到,yeoman等前端构建工具会帮我们管理依赖的js库,压缩和发布。
第二点,如何预判用户最可能访问的资源呢?用户的行为虽具有极大不确定性,但是还是能高命中的去预判 。
预判:良好的建模,设计良好的关系链,一次加载,加载全部关系树上一定深度的叶子、父以及兄弟资源。这些很可能是用户接下来要访问的。
诱导:页面良好的诱导设计。诱导用户访问我们已经预加载的这些资源。
接下来就是细节,根据数据大小确定如何加载,同步异步,前台后台。
大的数据:并且不是用户当前要访问的资源,在后台(异步的)预加载,如多媒体图片数据。
业务资源:一般不会很大,是些JSON/XML数据。缓存到localstorage。前端程序要数据时,先尝试查看网络是否畅通,畅通从远端拿,不畅通尝试从localstorage拿。如何保持localstorage同步?自己把握。甚至可以单独开线程跟后台同步:
如前端model已经加载,调用model.reload()去跟后台同步(会发一个rest get请求 /rest/model/1给后台)更新回来后会自动更新
实例代码:(如果本地有就从本地取,最好是判断网络畅通与否)
DS.Store.reopen
fetchLocal: (type, id, preload)->
if (@hasRecordForId(type, id))
@getById(type, id)
else
@find(type, id, preload)
fetchAllLocal: (type)->
localRecords=@all(type)
if localRecords.content? and localRecords.content.length>0
localRecords
else
@find(type)
App.ShopRoute = Ember.Route.extend
model:(params)->
@store.fetchLocal('shop',params.shop_id) //这里加载到store中的不仅仅是shop,shop中维护的关系树也被被加载进去了
shop model:
App.Shop = DS.Model.extend
name : DS.attr('string')
logoUrl : DS.attr('string')
addr : DS.attr('string')
phone : DS.attr('string')
orderLevel : DS.attr('string')
owner : DS.belongsTo('user') #商店所有者被加载
type : DS.attr('string')
createDate : DS.attr('date')
service : DS.belongsTo('service') #所属分类的孩子也就是同类型的商店被加载
items : DS.hasMany('item') #商店出售的商品被加载
后台的Shop实体bean
@Entity
@XmlRootElement
@Table(name="shop")
public class Shop extends EmberBean implements Serializable{
private static final long serialVersionUID = -5646667362601187548L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private String logoUrl;
private String addr;
private String phone;
@ManyToOne(cascade={CascadeType.REFRESH},fetch=FetchType.EAGER)
private User owner;
@ManyToOne(cascade={CascadeType.REFRESH},fetch=FetchType.EAGER)
private Service service;
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="shop")
private Set<Item> items;
private String type;
private Date createDate;
private int orderLevel;
关系树被配成EAGER加载了,当然是可以根据业务需要的加载层数加以控制,那就需要将这里配成LAZY,需要加载的数量也可以根据业务控制。
ok这样就可以了,维护一条线程去保持local数据的同步,不贴了。
缺点
预加载的流量使用率不高,也就是说有些预加载数据没有被真正使用就被释放,白白浪费流量,但是凡事各有利弊,什么事都是一样,掌握好度,才是真正的好。
消耗少量的流量能够获得相当高的用户体验,还是得能偿失的。
总结
总之,现在开源的前端MVC的库越来越多,这看起复杂的事情其实需要我们做的并不多。