请选择 进入手机版 | 继续访问电脑版

缓存整合设计及实现(数据缓存+图片缓存)

  [复制链接]
tcld2269 发表于 2015-12-24 16:11:38
本帖最后由 tcld2269 于 2015-12-28 08:56 编辑

要设计一个缓存的方案,包括数据的缓存(缓存从服务器接口获取的json字符串),图片的缓存(将图片下载到手机缓存目录中)整体结合在一起的东西,
在论坛搜索了好多关于缓存的文章,经过多家的思路及代码,现在整合成一套易用的、简捷的的代码框架,供大家分享!

设计思路:1.先从本地文件读取数据,如果读取到则直接返回
2.如果本地没有缓存,则前往服务器取数据,然后存到本地
3.如果本地缓存过期(服务器端数据进行了更新),则更新本地缓存文件


1.通用js,存放在common.js,每个页面都要引用。
var serverurl = "http://xxx.xxx.com/appservice.asmx";//服务器接口路径
var machineurl = "http://xxx.xxx.com";//服务器路径,用于图片显示

//缓存方法
function doCache(folder, id, url, callback) {
        readFile('/' + folder + '/' + id + '.json', function(ret, err) {
                if (ret.status) {
                        //如果成功,说明有本地存储,读取时转换下数据格式
                        //拼装json代码
                        //alert('取到缓存')
                        var cacheData = ret.data;
                        callback(JSON.parse(cacheData));
                        iCache($('.cache'));
                        //再远程取一下数据,防止有更新
                        ajaxRequest(url, 'GET', '', function(ret, err) {
                                if (ret) {
                                        if (cacheData != JSON.stringify(ret)) {
                                                //有更新处理返回数据
                                                //alert('更新缓存')
                                                callback(ret);
                                                //缓存数据
                                                writeFile(ret, id, folder);
                                                iCache($('.cache'));
                                        }
                                       
                                } else {
                                        alert('数据获取失败!');
                                }
                        })
                } else {
                        //如果失败则从服务器读取,利用上面的那个ajaxRequest方法从服务器GET数据
                        ajaxRequest(url, 'GET', '', function(ret, err) {
                                if (ret) {
                                        //处理返回数据
                                        //alert('没取到缓存')
                                        callback(ret);
                                        //缓存数据
                                        writeFile(ret, id, folder);
                                        iCache($('.cache'));
                                } else {
                                        alert('数据获取失败!');
                                }
                        })
                }
        })
}

//ajax请求
function ajaxRequest(url, method, datas, callBack) {
        var serverUrl = serverurl;
        var now = Date.now();
        api.ajax({
                url : serverUrl + url,
                method : method,
                cache : false,
                timeout : 30,
                dataType : 'json',
                data : {
                        values : datas
                }
        }, function(ret, err) {
                if (ret) {
                        callBack(ret, err);
                } else {
                        api.alert({
                                msg : ('错误码:' + err.code + ';错误信息:' + err.msg + '网络状态码:' + err.statusCode)
                        });
                }
        });
}

//读文件
function readFile(path, callBack) {
        var cacheDir = api.cacheDir;
        api.readFile({
                path : cacheDir + path
        }, function(ret, err) {
                callBack(ret, err);
        });
}
//写文件
function writeFile(json, id, path) {
        //缓存目录
        var cacheDir = api.cacheDir;
        api.writeFile({
                //保存路径
                path : cacheDir + '/' + path + '/' + id + '.json',
                //保存数据,记得转换格式
                data : JSON.stringify(json)
        }, function(ret, err) {

        })
}

//缓存图片
function iCache(selector) {
        selector.each(function(data) {! function(data) {
                        var url = selector.eq(data).attr("src");
                        var img = this;
                        var pos = url.lastIndexOf("/");
                        var filename = url.substring(pos + 1);
                        var path = api.cacheDir + "/pic/" + filename;
                        var obj = api.require('fs');
                        obj.exist({
                                path : path
                        }, function(ret, err) {
                                //msg(ret);
                                if (ret.exist) {
                                        if (ret.directory) {
                                                //api.alert({msg:'该路径指向一个文件夹'});
                                        } else {
                                                //api.alert({msg:'该路径指向一个文件'});
                                                //selector.eq(data).src=path;
                                                selector.eq(data).attr('src', null);
                                                path = api.cacheDir + "/pic/" + filename;
                                                selector.eq(data).attr('src', path);
                                                //console.log(selector.eq(data).attr("src"));
                                        }
                                } else {
                                        api.download({
                                                url : url,
                                                savePath : path,
                                                report : false,
                                                cache : true,
                                                allowResume : true
                                        }, function(ret, err) {
                                                //msg(ret);
                                                if (ret) {
                                                        var value = ('文件大小:' + ret.fileSize + ';下载进度:' + ret.percent + ';下载状态' + ret.state + '存储路径: ' + ret.savePath);
                                                } else {
                                                        var value = err.msg;
                                                };
                                        });
                                }
                        });
                }(data);
        });
};

2.调用方法。
//缓存ID
var id = api.pageParam.typeId;
//缓存目录,存储地址为 Caches/folder/id.json
var folder = "cartype";
//请求地址
var url = "/getCategoryByParentId?parentId=" + id + "&key=" + key;
//读取执行
doCache(folder, id, url, function(data) {
   //处理拼接html
   //图片样式加上cache
});

就是这么简单,请求数据的地方直接调用个doCache方法即可。省去写一大堆ajax请求代码,而且数据和图片缓存都帮你做好!!!

3.图片缓存的实现。
在需要图片缓存的页面,加上<script src="../../js/zepto.min.js"></script>

然后在doCache回调里面的图片的class加上cache即可自动实现图片缓存


备注:需要云模块中添加fs文件模块。

(附)上划翻页的实现。

如图上划到底部,自动加载下10条,没有数据的话就显示暂无内容。页数为0的话是用的缓存读取数据,保证了第一次的加载速度。
由于也用到了上面的缓存,所以也需要引用common.js和zepto.min.js



1)在apiready中定义当前页码

$api.setStorage("resou_index", 0);
load();
//上拉翻页
api.addEventListener({
        name : 'scrolltobottom'
}, function(ret, err) {
        $api.setStorage("resou_index", $api.getStorage("resou_index") - 0 + 1);
        load();
});


2)数据加载方法

//数据加载,first是判断是否重新刷新,index2是传入的当前页码
function load(first, index2) {
                        var index = $api.getStorage("resou_index");
                        if (index2 != null) {
                                index = index2;
                        }
                        var id = "resou";
                        var url = "/getGoodsTagList?tag=" + id + "&pageIndex=" + index + "&pageCount=20&key=" + key;
                        if (index == 0) {
                                //默认加载缓存
                                var folder = "getGoodsTagList";
                                doCache(folder, id, url, function(data) {
                                        dealWithHtml(data, first, index);
                                });
                        } else {
                                //分页后不加载缓存
                                ajaxRequest(url, 'get', '', function(data) {
                                        dealWithHtml(data, first, index);
                                });
                        }
                }

3)处理回调数据

function dealWithHtml(data, first, index) {
     //处理数据html的拼接
}


附件是common.js和zepto.min.js和分页的代码






本帖子中包含更多资源,您需要 登录 才可以下载或查看,没有帐号?立即注册

X

111条回复

疯男人 驾校小白 8Y币
没搞懂,用本地缓存与服务器请求数据进行比对,如果有更新用请求数据,如果没有更新就用缓存。问一下你写的这个缓存它快在哪里。
tcld2269 新手上路 440Y币
疯子老李 发表于 2016-1-16 11:27
头像我是base64的,因为我的程序要断网也可以用,所以数据都是必须缓存的,用文件缓存很不显示,因为还有 ...

文件缓存用的是官方的API
var cacheDir = api.cacheDir;
    /*
    例如:
    /var/mobile/Containers/Data/Application/4E376FDE-D595-4E08-B0A4-A06561B31000/Library/Caches/APICloud/Cache/XXXXXX
    */
应该不会只能存5m 2m吧,别的应用动辄200m以上的缓存怎么处理的?
闪退问题应该不用考虑,文件本身存在缓存目录,不会是像操作相册一样卡顿甚至闪退的。
可以尝试一下,无法满足您的情况可以一起解决一下,共同进步。
张三李四王五 驾校小白 89Y币
前排站位,出售瓜子饮料
kexicc 新手上路 512Y币
占位支持
itol123 新手上路 143Y币
必须臜啊,解决我很多问题
black2015 驾校小白 168Y币
在苹果里呢?
tcld2269 新手上路 440Y币

安卓苹果通用,截图就是iphone5的!
tcld2269 新手上路 440Y币
itol123 发表于 2015-12-26 18:41
必须臜啊,解决我很多问题

楼主也是遇到好多客户反映图片多的情况下速度慢,所以耗时3天研发出来的,经过新的项目的实验确实好用,才分享给大家,希望帮助到更多的人!
冷笑天 实习司机 52Y币
登录上来就是为了给楼主一个赞的!!
pingfan 实习司机 833Y币
赞一下,备用。
supercond 驾校小白 35Y币
顶一个,感谢分享!
12345678910... 12下一页
您需要登录后才可以回帖 登录

本版积分规则