smartjs - DataManager API
dataServices
数据服务的管理器;首先看下具体的代码
//数据服务
dataServices = st.factory({
name: "dataServices",
proto: {
//通过操作方法;type:操作类型; op:操作参数
operate: function(type, op) {…………},
//查询方法;op:操作参数
search: function(op) {…………},
//更新方法;op:操作参数
update: function(op) {……}
},
base: {
//查询接口
search: function(op) {},
//更新接口
update: function(op) {},
//通用初始化参数接口
initOptions : function(op){}
}
})
使用factory创建,加入了三个方法operate,search,update。使用的时候,直接通过这三个方法来操作具体注册的数据服务(在op中设定dsType)。
同时base定义了三个数据服务的三个基类接口,search,update,initOptions;
op:既设置的参数(options,在smartjs中统一做op的简写),只有六个固定参数。其他都是都是由具体的数据服务定义;
op = {
//数据服务类型
dsType : str,
//过滤参数
param :obj,
//过滤器
fitler : fn | obj
//更新的数据
data :obj,
//成功以后执行的方法
success : success,
//失败以后执行的方法
error : error
};
其中,param与filter可以根据不同的数据服务类型来区别使用,比如只是客户端的可以使用filter,服务端的可以使用params;
注意:虽然op中有了success,error,但添加dataService的时候,尽量使用promise的处理。
代码示例
通过dataServices的add(factory内置)的方法来注册数据服务;实现了search和update两个接口。另外一个initOptions是需要对op初始化的是重写
首先注册一个模拟后台异步数据服务 - server;只接受params来过滤数据:
var dataServices = st.dataServices,
dataManager = st.dataManager,
_db = [],
_cache = []; //将params解析成过滤方法
function buildFilterByParams(params) {
if (params) {
return function(item) {
var check = true;
$.each(params, function(name, value) {
if (item[name] !== value) {
check = false;
return check;
}
})
return check;
}
}
} //取对象数据,测试使用array只取第一条
function getData(data) {
return $.isArray(data) ? data[0] : data;
} function buildFitler(filter) {
if (filter && typeof filter === 'object') {
return buildFilterByParams(filter);
}
return filter;
} //模拟服务端异步返回数据,只接受params
dataServices.add("server", {
search: function(op) {
//模拟异步查询
setTimeout(function() {
var result,
filter = op.filter; result = filter ? _db.filter(filter) : _db; op.success && op.success(result);
}, 100);
},
update: function(op) {
//模拟异步更新
setTimeout(function() {
var filter = op.filter,
data = getData(op.data); if (filter) {
//测试使用,只更新第一条匹配数据
$.each(_db, function(i, item) {
if (filter(item)) {
_db[i] = data;
return false;
}
})
} else {
_db = op.data || [];
} op.success && op.success(op.data); }, 100);
},
initOptions: function(op) {
//初始化设置参数将params编译成filter过滤方法
op.filter = buildFilterByParams(op.params);
}
});
然后在注册一个模拟客户端取数据的缓存服务服务 - cache,使用filter进行过滤。
//模拟客户端本地存储
dataServices.add("cache", {
search: function(op) {
var result, filter = op.filter; result = filter ? _cache.filter(filter) : _cache; op.success && op.success(result);
},
update: function(op) {
var filter = op.filter,
data = getData(op.data); if (filter) {
//测试使用,只更新第一条匹配数据
$.each(_cache, function(i, item) {
if (filter(item)) {
_cache[i] = data;
return false;
}
})
} else {
_cache = op.data || [];
}
op.success && op.success(op.data);
},
initOptions: function(op) {
//生成fitler,当filter为obj类型时,编译成fn
op.filter = buildFitler(op.filter);
}
});
看一下server的测试用例,直接使用dataServices对象进行操作,使用dsType来设置具体的数据类型;
describe('dataServices Test', function() {
it("update", function(endTest) {
//更新server的数据
dataServices.update({
dsType: 'server',
data: [{
name: 'user1',
age: 20
}, {
name: 'user2',
age: 30
}],
success: function(result) {
expect(_db.length).toBe(2);
endTest();
}
});
}) it("search", function(endTest) {
//重新server的数据
dataServices.search({
dsType: 'server',
params: {
name: 'user1'
},
success: function(result) {
expect(result.length).toBe(1);
expect(result[0].age).toBe(20);
endTest()
}
}); })
});
dataManager
数据管理器,同样使用factory构建,但是选用的类型为'class',需动态初始化;扩展创建dm的方法-ceate和生成filter的方法-buildFilter;
另外在基类中,klassInit,get,set,onHandler,addHandler,fireHandler为实现方法;其他的都是接口,需要根据具体的数据管理进行实现;
//数据管理器
dataManager = st.factory({
name: "dataManager",
type: "class",
proto: {
//创建dm方法
create: function(type, op) {},
//生成fitler方法
buildFilter: function(filter,conf) {}
},
base: {
klassInit: function(op) {},
//dm初始化方法
init: function(op) {},
//获取数据
get: function(conf) {},
//设置数据
set: function(conf) {},
//注册方法到事件委托,handler委托名称:get,set,trigger
onHandler: function(handler, fnName, fn, priority, mode) {},
//添加事件委托
addHandler: function() {},
//执行事件委托
fireHandler: function(name, args) {},
//dm内置查询
innerSearch: function(op) {},
//dm内置更新
innerUpdate: function(op) {},
//检查数据是否为空
checkEmpty: function(data, conf) {},
//验证方法
validate: function() {},
//清空方法
clear: function() {},
//初始化数据服务配置方法
setDataSerive : function(config){}
}
});
添加datamanger示例
添加一个简单的table类型的数据管理,(注只做测试演示,与真正的datamanger-table不是同一个)
//添加一个简单的table类型的数据管理
dataManager.add("Table", {
init: function() {
this._data = [];
},
//dm内置查询
innerSearch: function(conf) {
var filter = conf ? buildFitler(conf.filter) : null;
return filter ? this._data.filter(filter) : this._data;
},
//dm内置更新
innerUpdate: function(conf) {
var isUpdate, _data = this._data,
data = conf.data,
updateData, filter; conf && (filter = buildFitler(conf.filter)); if (filter) {
updateData = getData(data);
//筛选数据
_data.forEach(function(item, i) {
if (filter(item)) {
_data[i] = updateData;
isUpdate = true;
return false;
}
})
isUpdate || _data.push(updateData);
} else {
this._data = data || [];
}
return data;
},
//判断数据是否为空
checkEmpty: function(data, conf) {
return data === undefined || data.length === 0;
},
//清空数据
clear: function() {
this._data = [];
}
});
在来看一下怎么使用这个dm,下面列子中使用了内置的查询和更新;
//创建一个tabel的manager
var dm1 = dataManager.create("Table"); it("update", function() {
dm1.innerUpdate({
data: [{
name: 'user1',
age: 10
}]
});
expect(dm1._data.length).toBe(1);
expect(dm1._data[0].name).toBe('user1');
}) it("search", function() {
var result = dm1.innerSearch();
expect(result.length).toBe(1);
expect(result[0].name).toBe('user1');
}) it("update by filter", function() {
//找不到匹配的数据,则插入新数据
dm1.innerUpdate({
data: {
name: 'user3',
age: 10
},
//方法过滤器
filter: function(user) {
return user.name == 'user3';
}
});
expect(dm1._data.length).toBe(2);
expect(dm1._data[1].name).toBe('user3'); //更新数据
dm1.innerUpdate({
data: {
name: 'user3',
age: 40
},
//方法过滤器
filter: function(user) {
return user.name == 'user3';
}
}); expect(dm1._data.length).toBe(2);
expect(dm1._data[1].age).toBe(40);
}) it("search by filter", function() {
var result = dm1.innerSearch({
//方法过滤器
filter: function(user) {
return user.name == 'user3';
}
});
expect(result.length).toBe(1);
expect(result[0].age).toBe(40);
}) it("search by params", function() {
var result = dm1.innerSearch({
//参数过滤器
filter: {
name: 'user3'
}
});
expect(result.length).toBe(1);
expect(result[0].age).toBe(40);
})
在结合dataService来看个查询的例子,在这里使用get操作,而不是innerSearch;get和set这两个动作都会进入数据管理流程,策略才会生效。而innerSearch和innerUpdate则是只查询dm内部。
在这个例子中,get动作会首先在dm内部查询,找不到数据,在会进入ds查询,然后将ds查询的数据同步到dm中。(详细的流程见dataManager介绍)
it("get from ds and update", function(endTest) {
dm1.clear();
//首先会在dm内部查询,找不到数据然后在到server上查询
dm1.get({
//设置数据服务为server
dataServices: {
dsType: 'server'
},
success: function(result) {
expect(result).toBeDefined();
expect(result[0].name).toBe('user1');
expect(dm1._data[0].name).toBe('user1');
endTest();
}
})
}) it("get from ds and no update", function(endTest) {
dm1.clear();
dm1.get({
//设置查询不更新
update: false,
dataServices: {
dsType: 'server'
},
success: function(result) {
expect(dm1._data.length).toBe(0);
endTest();
}
})
})
在看一个set的例子:
it("set to ds", function(endTest) {
//更新到ds
dm1.set({
data: [{
name: "userUpdate"
}],
dataServices: {
dsType: 'server'
},
success: function(result) {
expect(_db.length).toBe(1);
expect(_db[0].name).toBe('userUpdate');
endTest();
}
}) }) it("set to ds by params", function(endTest) {
//根据条件更新到ds,条件同时在dm和ds中生效
dm1.set({
data: [{
name: "userUpdate"
}],
params: {
id: 1
},
dataServices: {
dsType: 'server'
},
success: function(result) {
expect(_db.length).toBe(2);
expect(_db[0].name).toBe('userUpdate');
endTest();
}
})
})
下篇详细介绍策略参数的api和场景分析
smartjs - DataManager API的更多相关文章
- smartjs - DataManager 场景示例分析 - 数据懒加载
发一张policy的参数图设置图: 场景1 - 数据的懒加载/延迟加载 在很多时候,为了提高网页的加载速度,减少不必要的开销,会将页面的数据拆分成几个部分,首先加载呈现可视区域内的数据,然后剩下来的会 ...
- smartjs 0.3 DataManager 发布&介绍
在0.3版加入了DataManager,基于策略的数据管理模块:是SmartJS中比较重要的一个系列.整个个DataManager模块包括有:dataManager,dataPolicyManager ...
- smartJS 0.1 API 讲解 - PromiseEvent
上篇简单的介绍smartjs了一些通用方法的api.这篇介绍基础的PromiseEvent(这个名字一直没想好,以前准备用callbacks的,但避免与jquery混淆,st的命名空间可以直接挂到$上 ...
- smartJS 0.1 API 讲解 - FlowController
本篇介绍0.1版中最后一个特性,FlowController:同时也对第一版总结一下,因为近两年全部都是在搞前端,都是做一些js框架类的东西,也做了不少有意思的功能,做smartjs对我来说一个是对自 ...
- smartJS 0.1 API 讲解 - Trigger
上篇介绍了PromiseEvent,本篇介绍Trigger - 基于Promise的aop的体现:(感觉自己的对这些命名一直都很挫,也懒得想了,所以就凑合的用) Trigger 在目标对象上加入触发器 ...
- 百度地图API使用记录
用户数据图层的总教程: 就是把用户数据存到LBS云里面,应用从云里面读数据 http://developer.baidu.com/map/jsdevelop-9.htm 上传数据的地方: http:/ ...
- SmartJS 系列规划分享和背景介绍
发布了smartjs后,有朋友问:“没看懂究竟是干嘛的”.唉,打击了,每次我都想高唱其实你不懂我的心. 今天把相关的东西都整理了一遍,给大家介绍一下.里面绝大多数都已经实现过,有些则是有新的思路重做或 ...
- SmartJS 第一期(0.1)发布 - AOP三剑客
隔了好久才终于又发布了一点东西,SmartJS是最近才开始搞的一个开源js库,目的是做一些比较有特点的事情(smartjs暂时也是依赖于jquery). SmartJS的内容规划比较多,也无法在短时间 ...
- 【高德地图API】从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索
原文:[高德地图API]从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索 摘要:地图服务,大家能想到哪些?POI搜素,输入提示,地址解析,公 ...
随机推荐
- js脚本语言基础和数组
js和PHP中,字符串赋值:要使用"双引号"或"单引号"引起来:例如:var c="你好"不同类型进行数学运算,要转换,类型转换:强制转换p ...
- iOS开发----地图与导航--定位和位置信息获取
要实现地图.导航功能,往往需要先熟悉定位功能,在iOS中通过Core Location框架进行定位操作.Core Location自身可以单独使用,和地图开发框架MapKit完全是独立的,但是往往地图 ...
- javaweb学习总结(十六)——JSP指令
一.JSP指令简介 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分. 在JSP 2.0规范中共定义了三个指令: pa ...
- aehyok.com的成长之路二——技术选型
前言 首先奉上个人网站地址传送门:aehyok.com 在上一篇博客中http://www.cnblogs.com/aehyok/p/3934197.html主要简单的介绍了自己做个人网站的初衷, ...
- MongoDB图形化管理工具
NoSQL的运动不止,MongoDB 作为其中的主力军发展迅猛,也带起了一股开发图形化工具的风潮:气死反过来说,看一个产品是否得到认可,可以侧面看其第三方工具的数量和成熟程度:简单的收集了MongoD ...
- 隐藏nginx 版本号信息
为了安全,想将http请求响应头里的nginx版本号信息隐藏掉: 1. nginx配置文件里增加 server_tokens off; server_tokens作用域是http server loc ...
- Android UI系列-----时间、日期、Toasts和进度条Dialog
您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...
- BarEditItem ContentTemplate
<dxb:BarEditItem Name="txtSearch" > <dxb:BarEditItem.ContentTemplate> <Data ...
- C++程序中调用MPI并行的批处理命令
问题来源:在使用MPI时,将程序并行实现了,运行时需要在dos窗口下输入批处理命令,以完成程序的执行. 如:mpiexec -localroot -n 6 d:/mpi/pro.exe 但每次这样挺麻 ...
- Android gradle问题解决: This app has been built with an incorrect configuration. Please configure your build for VectorDrawableCompat
1. 问题描述: Android Studio在运行模拟器某些机型或者真机某些机型的时候发生闪退. 错误如下: Java.lang.RuntimeException: Unable to start ...