zoukankan      html  css  js  c++  java
  • smartjs

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

  • 相关阅读:
    题解 [APIO2014]连珠线
    题解 [ZJOI2019]语言
    题解 Hero meet devil
    题解 [BJOI2019]奥术神杖
    题解「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set
    题解 Sue的小球/名次排序问题/方块消除/奥运物流
    题解 「一本通 5.4 练习 1」涂抹果酱
    Mybatis的类型转换
    面试题:微服务熔断降级限流
    面试题:微服务网关
  • 原文地址:https://www.cnblogs.com/zhh8077/p/3802350.html
Copyright © 2011-2022 走看看