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的github上查看

smartjs - DataManager API的更多相关文章

  1. smartjs - DataManager 场景示例分析 - 数据懒加载

    发一张policy的参数图设置图: 场景1 - 数据的懒加载/延迟加载 在很多时候,为了提高网页的加载速度,减少不必要的开销,会将页面的数据拆分成几个部分,首先加载呈现可视区域内的数据,然后剩下来的会 ...

  2. smartjs 0.3 DataManager 发布&介绍

    在0.3版加入了DataManager,基于策略的数据管理模块:是SmartJS中比较重要的一个系列.整个个DataManager模块包括有:dataManager,dataPolicyManager ...

  3. smartJS 0.1 API 讲解 - PromiseEvent

    上篇简单的介绍smartjs了一些通用方法的api.这篇介绍基础的PromiseEvent(这个名字一直没想好,以前准备用callbacks的,但避免与jquery混淆,st的命名空间可以直接挂到$上 ...

  4. smartJS 0.1 API 讲解 - FlowController

    本篇介绍0.1版中最后一个特性,FlowController:同时也对第一版总结一下,因为近两年全部都是在搞前端,都是做一些js框架类的东西,也做了不少有意思的功能,做smartjs对我来说一个是对自 ...

  5. smartJS 0.1 API 讲解 - Trigger

    上篇介绍了PromiseEvent,本篇介绍Trigger - 基于Promise的aop的体现:(感觉自己的对这些命名一直都很挫,也懒得想了,所以就凑合的用) Trigger 在目标对象上加入触发器 ...

  6. 百度地图API使用记录

    用户数据图层的总教程: 就是把用户数据存到LBS云里面,应用从云里面读数据 http://developer.baidu.com/map/jsdevelop-9.htm 上传数据的地方: http:/ ...

  7. SmartJS 系列规划分享和背景介绍

    发布了smartjs后,有朋友问:“没看懂究竟是干嘛的”.唉,打击了,每次我都想高唱其实你不懂我的心. 今天把相关的东西都整理了一遍,给大家介绍一下.里面绝大多数都已经实现过,有些则是有新的思路重做或 ...

  8. SmartJS 第一期(0.1)发布 - AOP三剑客

    隔了好久才终于又发布了一点东西,SmartJS是最近才开始搞的一个开源js库,目的是做一些比较有特点的事情(smartjs暂时也是依赖于jquery). SmartJS的内容规划比较多,也无法在短时间 ...

  9. 【高德地图API】从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索

    原文:[高德地图API]从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索 摘要:地图服务,大家能想到哪些?POI搜素,输入提示,地址解析,公 ...

随机推荐

  1. paip java.net.SocketException No buffer space available的解决办法及总结

    java.net.SocketException No buffer space available的解决办法及总结 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来 ...

  2. iOS-图片拉伸技巧

    iOS开发中我们会遇到渐变的背景,内容可变的流式标签,聊天气泡(QQ聊天气泡),由于内容是可变的,宽度和高度同样可变,这样就是导致每次出现的尺寸与之前不一样.如果是需要设置的比较的多,估计美工会烦死, ...

  3. [转]Oracle因安装时未设定字符集导致中文乱码的解决方案

    在CentOS 6.4上安装Oracle 11g没有设定字符集,采用的是操作系统默认字符集:WE8MSWIN1252,将字符集修改为:AL32UTF8. SQL> select userenv( ...

  4. ArcGIS Server新建主题图服务的步骤

    ArcGIS Server新建主题图服务的步骤: 1.修改数据库模型图(PowerDesigner) 2.修改lygis.gdb文件数据库(发布时可以快速把表结构从gdb数据库拷贝到客户服务器的SDE ...

  5. 数据采集:完美下载淘宝Ip数据库 简单的程序节省60元人民币而不必购买数据库

    曾经做网站类型的程序时,经常需要收集客户端的访问数据,然后加以分析.这需要一个Ip数据库,数据表中显示Ip所在的省份市区等信息.网络上有流传的Ip纯真数据库,一些公开的Web服务也可以查询Ip地址信息 ...

  6. 如何在servlet取得spring beans (autowired)(转)

    在应用中一般普通的JavaPojo都是由Spring来管理的,所以使用autowire注解来进行注入不会产生问题,但是有两个东西是例外的,一个是 Filter,一个是Servlet,这两样东西都是由S ...

  7. INFO - InstallShield中的InstallScript工程Setup.exe /s的使用细节

    在InstallShield的各种工程类型中,Basic MSI工程Build出的安装包基于Windows Installer标准,所以默认就支持静默安装(至于如何静默安装,请自行补充相关知识).而对 ...

  8. 【转】iOS超全开源框架、项目和学习资料汇总

    iOS超全开源框架.项目和学习资料汇总(1)UI篇iOS超全开源框架.项目和学习资料汇总(2)动画篇iOS超全开源框架.项目和学习资料汇总(3)网络和Model篇iOS超全开源框架.项目和学习资料汇总 ...

  9. 分布式Hadoop安装(一)

    本文旨在介绍通过两台物理节点,实现完全分布式hadoop程序的部署 writen by Bob Pan@20140609 环境介绍: 主机名 机器IP 用途 描述 Hadoop0 192.168.80 ...

  10. InteliJ IDEA15 安装jrebel破解文件

    使用InteliJ IDEA这个工具感觉比eclipse好用,例如它在没有源码的情况下自动反编译源码等,但是在使用的时,有个很不爽的地方就是不能实时编译,导致java代码更改了一点代码就需要重启项目, ...