解题思路:如果我们需要获取离线信息,那么必须将之前的数据缓存到本地,那么前后端之间接通数据就必须通过接口来实现,那么仅需从封装并改造接口就可以实现离线功能,即,从将之前访问过的页面的所有接口数据都保存下来,待离线的时候再重新调用该接口返回的数据(注意要对每个请求和参数都设置成唯一值),这中间,可能会有离线保存的问题,但是仅需要例如,某个操作需要后端传回id才能实现该功能,那么便可以先给该id存储一个假id然后如果要进行其他操作可以进行预留或者跳过,待联网之后,第一个接口数据联通并返回了id,那么,后续的其他接口id也进行请求。
该功能有点类似队列,先进先出。在离线的时候把所有的请求地址和参数都存储下来,待上线之后再自动执行该请求
第一步先将接口封装代码如下:(此处的作用是为了存储页面请求过的数据)
// const baseUrl = 'http://192.168.2.60:9800/rzzxmobile'; // 后端的主机名 + 端口号
import {
rez_path
} from "@/common/js/warehouse.js"
// 带 Token 请求
const httpTokenRequest = (opts) => {
let httpDefaultOpts = {
url: rez_path + opts.url,
data: opts.data,
method: opts.method || 'GET',
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
// dataType: 'json',
}
let promise = new Promise(function(resolve, reject) {
uni.request(httpDefaultOpts).then(
(e) => {
let res=e[1]
if (res.statusCode == 200) {
let storeData = uni.getStorageSync('storeData')
if (storeData != 'undefined' && storeData != null && storeData.length > 0) {
var flag = false
storeData.forEach((k, j) => {
if (k.url == opts.url&&looseEqual(k.params, opts.data)) {
k.data=res
flag = true
}
})
if (!flag) {
let item = {}
item.url = opts.url
item.data = res
item.params = opts.data
storeData.push(item)
}
} else {
storeData = []
let item = {}
item.url = opts.url
item.data = res
item.params = opts.data
storeData.push(item)
}
uni.setStorageSync('storeData', storeData)
resolve(res)
} else {
console.log(res)
console.log("请求错误信息", res.data.message);
uni.showToast({
icon: 'none',
title: res.data.message,
duration: 3000
})
return Promise.reject(res.data.message);
}
}
).catch(
(response) => {
reject(response)
}
)
})
return promise
}
// 去重
function deWeight(arr) {
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i].ID == arr[j].ID) {
arr.splice(j, 1);
//因为数组长度减小1,所以直接 j++ 会漏掉一个元素,所以要 j--
j--;
}
}
}
return arr;
}
// 找相同formdata数据
//判断两个对象是否相同(包含绝对相等和他们是否有相同的形状)
function looseEqual(a, b) {
if (a === b) { //如果是绝对相等就直接返回true
return true;
}
//如果不是绝对相等就哦按的他们是否有相同的形状
var isObjectA = isObject(a);
var isObjectB = isObject(b);
if (isObjectA && isObjectB) { //两个均是对象
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) { //如果都是数组
if (a.length === b.length) { //如果长度相等
return a.every(function(e, i) { //用every和递归来比对a数组和b数组的每个元素,并返回
return looseEqual(e, b[i])
})
}
//长度都不等直接返回false
return false;
} else if (a instanceof Date && b instanceof Date) { //如果是Date 则直接getTime 比较
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) { //对象的比较
//拿到两个对象的key
var keysA = Object.keys(a);
var keysB = Object.keys(b);
if (keysA.length === keysB.length) { //如果keys相等
return keysA.every(function(key) { //用every和递归来比对a对象和b对象的每个元素值,并返回
return looseEqual(a[key], b[key]);
})
}
//长度都不等直接返回false
return false;
} else {
return false
}
} catch (e) {
return false
}
} else if (!isObjectA && !isObjectB) { //如果都不是对象则按String来处理
return String(a) === String(b)
} else {
return false
}
}
function isObject(obj) {
return obj !== null && typeof obj === 'object'
}
// formdata转json
function changeStyle(obj) {
var objData = {}
obj.forEach(function(curValue, index, arr) {
objData[index] = curValue;
});
return objData
}
// 导出去
export default httpTokenRequest;
第二步,在离线时释放之前存储过的数据,部分代码如下
// import request from '@/common/js/request_rez.js'
import request from "./request";
// 检测是否有网
// function network() {
// var that = this
// let p = new Promise(function(resolve, reject) {
// uni.request({
// url: 'www.baidu.com',
// success: function(res) {
// console.log(res)
// console.log("这是有网")
// resolve(true);
// },
// fail: function(res) {
// console.log(res)
// resolve(false);
// }
// })
// });
// return p;
// }
function changeStyle(obj) {
var objData = {}
obj.forEach(function(curValue, index, arr) {
objData[index] = curValue;
});
return objData
}
// 通用接口
function common(parameter, name) {
// network().then((net_work)=>{
// console.log(net_work)
// })
// uni.getNetworkType({
// success: (res2) => {
// if (res2.networkType == 'none') {
// }
// },
// })
// 控制离线或者线上
const app = getApp();
// console.log(app.$global.web_flag)
// var flag =true
// uni.getNetworkType({
// success: (res) => {
// if (res.networkType == 'none') {
// flag = false
// }
// }
// })
if (app.$global.web_flag) {
let requestQueue = uni.getStorageSync('requestQueue')
let result = ''
// 调用离线时存储的接口
if (requestQueue != 'undefined' && requestQueue != null && requestQueue.length > 0) {
for(let i=0;i<requestQueue.length;i++){
if(requestQueue[i].parameter.hasOwnProperty('recordid')){
if(String(requestQueue[i].parameter.recordid).search("lx_") != -1){
// 涉及到离线新增条目的id直接跳过
continue;
}
}
result = request({
url:requestQueue[i].name.api,
method: 'post',
data: requestQueue[i].parameter
})
requestQueue.splice(i, 1)
}
console.log(requestQueue)
uni.setStorageSync('requestQueue', requestQueue)
}
result = request({
url: name.api,
method: 'post',
data: parameter
})
return result
} else {
let requestQueue = uni.getStorageSync('requestQueue')
// 存储离线时调用接口的动作
if (requestQueue != 'undefined' && requestQueue != null && requestQueue.length > 0) {
let item = {}
item.parameter = parameter
item.name = name
item.time = new Date()
requestQueue.push(item)
uni.setStorageSync('requestQueue', requestQueue)
} else {
requestQueue = []
let item = {}
item.parameter = parameter
item.name = name
item.time = new Date()
requestQueue.push(item)
uni.setStorageSync('requestQueue', requestQueue)
}
console.log(requestQueue)
// 读取每个页面的接口存储的信息
let data = ''
let storeData = uni.getStorageSync('storeData')
if (storeData != 'undefined' && storeData != null && storeData.length > 0) {
if (storeData.find(storeData => storeData.url === name.api && looseEqual(storeData.params, parameter))) {
let tem_data = storeData.find(storeData => storeData.url === name.api && looseEqual(storeData.params,
parameter))
data = tem_data.data
} else {
data = {
data: {
code: "0",
data: [],
message: "无该缓存数据"
}
}
}
}
return Promise.resolve(data)
}
}
// 找相同formdata数据
//判断两个对象是否相同(包含绝对相等和他们是否有相同的形状)
function looseEqual(a, b) {
if (a === b) { //如果是绝对相等就直接返回true
return true;
}
//如果不是绝对相等就哦按的他们是否有相同的形状
var isObjectA = isObject(a);
var isObjectB = isObject(b);
if (isObjectA && isObjectB) { //两个均是对象
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) { //如果都是数组
if (a.length === b.length) { //如果长度相等
return a.every(function(e, i) { //用every和递归来比对a数组和b数组的每个元素,并返回
return looseEqual(e, b[i])
})
}
//长度都不等直接返回false
return false;
} else if (a instanceof Date && b instanceof Date) { //如果是Date 则直接getTime 比较
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) { //对象的比较
//拿到两个对象的key
var keysA = Object.keys(a);
var keysB = Object.keys(b);
if (keysA.length === keysB.length) { //如果keys相等
return keysA.every(function(key) { //用every和递归来比对a对象和b对象的每个元素值,并返回
return looseEqual(a[key], b[key]);
})
}
//长度都不等直接返回false
return false;
} else {
return false
}
} catch (e) {
return false
}
} else if (!isObjectA && !isObjectB) { //如果都不是对象则按String来处理
return String(a) === String(b)
} else {
return false
}
}
function isObject(obj) {
return obj !== null && typeof obj === 'object'
}
module.exports = {
common: common,
}