解题思路:如果我们需要获取离线信息,那么必须将之前的数据缓存到本地,那么前后端之间接通数据就必须通过接口来实现,那么仅需从封装并改造接口就可以实现离线功能,即,从将之前访问过的页面的所有接口数据都保存下来,待离线的时候再重新调用该接口返回的数据(注意要对每个请求和参数都设置成唯一值),这中间,可能会有离线保存的问题,但是仅需要例如,某个操作需要后端传回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,

}

















Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐