技术标签: 小程序 javascript
#主要的封装是wxRequest、wxRequestGet、wxRequestPost、wxRequestPromise、headers这几个函数,由于太过赘余不进行截图展示,可以看utils.js
#wxRequest方法
wxRequest其实跟原始的wx.request没有太大的不同,相当于一个中间键,可以更灵活的配置,可维护性更高,一致请求,首先来解析一些wxRequest,以下简介的说明下
获取本地存储的token(ssoAuthToken),如果token存在就设置header,直接请求接口,不存在就重新刷新token之后,再请求该接口
isLoading是用来判断某些接口是否需要wx.showLoading(加载中),就可能我不是所有的接口都需要loading的提示,只是部分请求时长比较久的接口需要,所以我们存了一个需要loading的数组,判断请求的接口url是否存在这个数组中,存在就显示loading,而这个数组的数据都是从api.js里面拿出来的,如图一所示,我们每个API都是以对象的方式存的,为什么这样做呢,主要是想灵活点,例如我可能需要调不同的服务器的接口,那么我就可以配置多一个baseUrl的字段,调接口就传多一个baseUrl,如果没有传就使用默认的服务器域名
always方法其实是相当于请求失败的一个拦截器,请求失败后做什么事情
#wxRequestPromise方法
是加入Promise的一个操作,方便我们做链式调用,最后执行resolve或reject方法,返回一个Promise对象,供我们使用.then
#演示不同的请求方法代码片段
#util.wxRequest util.wxRequest({ url: api.queryServiceAreaByName.url, data: queryServiceAreaByName, method: 'POST', success: function (res) { console.log(res); } })
#util.wxRequest
util.wxRequest({
url: api.queryServiceAreaByName.url,
data: queryServiceAreaByName,
method: 'POST',
success: function (res) {
console.log(res);
}
})
#util.wxRequestPost
util.wxRequestPost({
url: api.getEvaluateList.url,
data,
})
.then(res => res.data.data)
.then(data => {
console.log('data', data);
})
#util.wxRequestPost util.wxRequestPost({ url: api.getEvaluateList.url, data, }) .then(res => res.data.data) .then(data => { console.log('data', data); })
#图一
const config = require('../config/config.js');
const dayjs = require("./dayjs");
const api = require("./api.js");
const app = getApp();
const loadingApi = [
api.queryServiceAreaInPoint.url,
api.queryConstructionInPoint.url,
api.queryServiceAreaByName.url,
api.queryServiceAreaWithPoint.url,
api.getUserDetails.url,
api.addEvaluateItem.url,
api.queryServiceAreaDetailInMap.url,
api.queryOrderByPhone.url
];
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
function headers(header) {
header = header || {};
//小应用特殊头
header['X-Requested-isWXAPP'] = 'YES';
//session_id , vmc_uid 处理
var session_id = wx.getStorageSync('_SID'),
vmc_uid = wx.getStorageSync('_VMC_UID');
var ownshop = wx.getStorageSync('own_shop');
// SID
if (session_id)
header['X-WxappStorage-SID'] = session_id;
if (ownshop) {
header['X-REQUESTED-HEADER-VSHOPID'] = ownshop;
}
// UID
if (vmc_uid)
header['X-WxappStorage-VMC-UID'] = vmc_uid;
if (wx.getStorageSync('merchant_id')) {
header['X-WxappStorage-MCH-ID'] = wx.getStorageSync('merchant_id');
}
if (config.RUN_ON_SAAS && wx.getExtConfig) {
var ext_vars = wx.getExtConfigSync();
// SAAS RUN TYPE
header['x-requested-saas-mode'] = 'APP';
header['x-requested-saas-app'] = ext_vars.host_pre;
header['x-requested-saas-client'] = ext_vars.client_id;
header['x-requested-saas-order'] = ext_vars.order_id;
}
return header;
}
function wxRequest(params) {
let ssoAuthToken = wx.getStorageSync('sso_auth_token') || null;
let isLoading = loadingApi.includes(params.url);
if (!params.header) {
params.header = {};
}
// loading加载
if (isLoading) {
wx.showLoading({
title: '加载中',
})
}
// 如果没有baseUrl使用config上配置的,如果有使用传入的
if (!params.baseUrl) {
params.url = config.BASE_URL + params.url;
} else {
params.url = params.baseUrl + params.url;
}
headers(params.header);
//content-type
params.header['content-type'] = params.header['content-type'] ? params.header['content-type'] : 'application/json';
if (ssoAuthToken) {
params.header['accessToken'] = ssoAuthToken.accessToken;
params.header['refreshToken'] = ssoAuthToken.refreshToken;
let serviceAreaIds = ssoAuthToken.serviceAreas.map(item => item.id);
if (params.data.serviceAreaIdList) {
params.header['serviceAreaIds'] = params.data.serviceAreaIdList[0];
} else {
params.header['serviceAreaIds'] = serviceAreaIds[0];
}
}
// 拿到接口数据后进行处理,相当于拦截器
var always = function (res) {
console.log('util.js:always')
if (res.data && !res.data.success) {
var res_redirect = res.data.redirect;
if (res_redirect && res_redirect.match && res_redirect.match(/passport-login/i)) {
//服务端登录状态丢失,重新登录
delete (app.globalData.member);
return checkMember(function () {
wx.showModal({
title: '已刷新用户登录状态',
content: '请重新进入',
showCancel: false,
success: function (res) {
wx.navigateBack();
}
});
});
}
}
};
if (params.success) {
var _tmp = params.success;
params.success = null;
params.success = function (res) {
always(res);
_tmp(res);
if (isLoading) {
// setTimeout(function () {
wx.hideLoading();
// }, 1000)
}
};
} else {
params.success = function (res) {
always(res);
};
}
// 获取ssoAuthToken,如果ssoAuthToken里的accessToken、refreshToken过期了,刷新后再请求接口
if (ssoAuthToken) {
let timestamp = dayjs(new Date()).valueOf();
if (ssoAuthToken.expiresIn < timestamp) {
// 这里过期的时候可能执行多次,因为一个页面可能调了多个接口,可以做500ms的队列
if (app && app.globalData) {
app.globalData.loginModal.getTokenByRefreshToken(params);
}
} else {
wx.request(params);
}
} else {
wx.request(params);
}
}
// promise 封装 wxRequest
const wxRequestPromise = (method) =>
(params) => new Promise((resolve, reject) => {
if (!params.url) throw 'params url not found'
params.method = method
paramsFn(params, 'success', resolve)
paramsFn(params, 'fail', reject)
console.log('params', params);
wxRequest(params)
})
const paramsFn = (params, fnName, cb) => {
const fn = params[fnName] || (() => { })
params[fnName] = null
params[fnName] = (res) => {
fn(res)
cb(res)
}
}
function wxUpload(params) {
if (!params.header) {
params.header = {};
}
headers(params.header);
//content-type
params.header['content-type'] = 'multipart/form-data';
wx.uploadFile(params);
}
const checkMemberHook = function (page_ins, page_callback_fn) {
let the_member = app.globalData.member;
try {
page_ins.setData({
'member': the_member,
});
} catch (e) {
//TODO
}
typeof page_callback_fn == 'function' && page_callback_fn(the_member);
}
function checkMember(callback, is_retry) {
var _this = this;
clearTimeout(app.getMemberTimer);
app.getMemberTimer = setTimeout(function () {
console.log('begin getMember at ' + new Date());
app.getMember(function (member) {
if (member.member_id) {
return checkMemberHook(_this, callback);
}
wxRequest({
url: config.BASE_URL + '/openapi/toauth/callback/wechat_toauth_wxapppam/callback',
method: 'POST',
data: member,
success: function (res) {
if (!res.data.result || res.data.result != 'success') {
console.info('oauth server callback res error:');
console.info(res);
wx.showModal({
title: '授权失败',
content: res.data.data || '',
showCancel: (!is_retry),
confirmText: (!is_retry ? '重试' : '确定'),
success: function (res) {
if (!is_retry && res.confirm) {
checkMember.apply(_this, [callback, true]);
}
}
});
} else {
// app.globalData.member.member_id = res.data.data.member_id;
// app.globalData.member.openid = res.data.data.openid;
Object.assign(app.globalData.member, res.data.data);
checkMemberHook(_this, callback);
}
},
complete: function () {
}
});
});
}, 0);
}
function formatArea(area_str = '') {
var match = area_str.match(/mainland:([^:]+)/);
if (match) {
return match[1].split('/').join('-');
}
}
function fix_img_url(url) {
if (url.match(/^http([s]*):/)) {
return url;
}
return 'https:' + url;
}
//倒计时
function count_down(that, intDiff) {
function cd() {
var day = 0,
hour = 0,
minute = 0,
second = 0; //时间默认值
if (intDiff > 0) {
day = Math.floor(intDiff / (60 * 60 * 24)).toString();
hour = (Math.floor(intDiff / (60 * 60)) - (day * 24)).toString();
minute = (Math.floor(intDiff / 60) - (day * 24 * 60) - (hour * 60)).toString();
second = (Math.floor(intDiff) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)).toString();
}
if (day <= 9)
day = '0' + day;
if (hour <= 9)
hour = '0' + hour;
if (minute <= 9)
minute = '0' + minute;
if (second <= 9)
second = '0' + second;
if (day == 0 && hour == 0 && minute == 0 && second == 0) {
clearInterval(cd);
}
that.setData({
countdown: {
days: day,
hours: hour,
minutes: minute,
seconds: second,
}
});
intDiff -= 1;
}
setInterval(cd, 1000)
};
function scene_parse(scene) {
if (scene) {
try {
var scene_obj = JSON.parse(decodeURIComponent(scene));
} catch (e) {
return false;
}
if (typeof scene_obj == 'object') {
return scene_obj;
}
return false;
}
return false;
}
/*获取当前页带参数的url*/
function getCurrentPageUrlWithArgs() {
var pages = getCurrentPages() //获取加载的页面
var currentPage = pages[pages.length - 1] //获取当前页面的对象
var url = currentPage.route //当前页面url
var options = currentPage.options //如果要获取url中所带的参数可以查看options
//拼接url的参数
var urlWithArgs = url + '?'
for (var key in options) {
var value = options[key]
urlWithArgs += key + '=' + value + '&'
}
urlWithArgs = urlWithArgs.substring(0, urlWithArgs.length - 1)
return urlWithArgs
}
function gotoIndex() {
wx.switchTab({
url: "/pages/index/index"
});
}
function merchantShare(url) {
let merchant_id;
if (wx.getStorageSync('merchant_id')) {
merchant_id = wx.getStorageSync('merchant_id');
} else {
merchant_id = 0;
}
if (url.indexOf("?") != -1) {
url += '&merchant_id=' + merchant_id
} else {
url += '?merchant_id=' + merchant_id
}
return url;
}
function getQuery(url, query) {
if (url.indexOf('?') < 0)
return;
var arr = url.split('?');
var query_arr = arr[1].split('&');
for (var i = 0; i < query_arr.length; i++) {
let single_arr = query_arr[i].split('=');
console.log('single_arr', single_arr);
if (!single_arr[1]) continue;
query[single_arr[0]] = single_arr[1];
}
return query;
}
function setTabBarBadge() {
wxRequest({
url: config.BASE_URL + '/openapi/cart/count',
success: function (res) {
try {
if (res.data.data.quantity > 0) {
wx.setTabBarBadge({
index: 1,
text: res.data.data.quantity.toString(),
success: function () {
},
fail: function () {
},
complete: function (e) {
}
})
} else {
wx.removeTabBarBadge({
index: 1,
success: function () {
},
fail: function () {
},
complete: function (e) {
}
})
}
} catch (e) {
console.log(e)
}
}
});
}
// 过滤显示服务区的拥有服务图标
function filterServiceProvidedIcon(params) {
if (!params) {
return []
}
var IconObj = {
//餐饮 coffeeActive
catering: 'coffeeActive',
//住宿 oilActive
accommodation: 'oilActive',
//购物 shoppingActive
shopping: 'shoppingActive',
//卫生间 toiletActive
toilet: 'toiletActive',
//停车场 park
parking_lot: 'park',
//加油站 gas
fuel_filling: 'gas',
//充电桩 charge
recharge: 'charge',
//加气站 naturalGas
air_entrapping: 'naturalGas',
//维修 maintain
maintenance: 'maintain',
//其他服务 more
}
var originIcon = params.split(',')
var fileterIcon = originIcon.map(element => IconObj[element])
return fileterIcon.filter(ele => ele)
}
function setHtmlSnip(keyword, text) {
return '<div>' + text.replace(new RegExp(keyword, 'g'), `<span style="color: blue">${keyword}</span>`) + '</div>'
}
const wxRequestGet = wxRequestPromise('GET')
const wxRequestPost = wxRequestPromise('POST')
function getUserInfo() {
return new Promise((resolve, reject) => {
const wxUserInfo = wx.getStorageSync('wx_userinfo') || {}
if (wxUserInfo.nickName) {
resolve(wxUserInfo)
} else {
wx.getUserInfo({
success: (result) => {
wx.setStorage({
data: { ...wxUserInfo, ...result.userInfo },
key: 'wx_userinfo',
})
resolve(result.userInfo)
},
complete: () => resolve({}),
})
}
})
}
const buriedPoint = async (data = {}) => {
const { scene } = wx.getLaunchOptionsSync()
const wxUserInfo = await getUserInfo()
// console.log('wxUserInfo', wxUserInfo);
data = {
...data,
buriedPointType: data.path ? 0 : 1,
type: Number(scene !== 1001),
nickName: wxUserInfo.nickName || '',
phoneNumber: wxUserInfo.phoneNumber || '',
}
console.log('buriedPoint', data);
return wxRequestPost({
url: api.buriedPoint.url,
data,
})
}
const checkLogin = () => new Promise((resolve, reject) => {
const app = getApp()
if (app.globalData.checkLogin) {
resolve()
} else {
const cb = app.checkLoginReadyCallback
app.checkLoginReadyCallback = () => {
typeof cb === 'function' && cb()
resolve()
};
}
})
const getTime= function(value, flag) {
let theTime = parseInt(value);// 秒
let middle= 0;// 分
let hour= 0;// 小时
let result = ""
if(theTime > 60) {
middle= parseInt(theTime/60);
theTime = parseInt(theTime%60);
if(middle> 60) {
hour= parseInt(middle/60);
middle= parseInt(middle%60);
}
if(flag) {
result = ""+parseInt(theTime)+"秒"
}
} else {
result = ""+parseInt(theTime)+"秒"
}
if(middle > 0) {
result = ""+parseInt(middle)+"分钟"+result;
}
if(hour> 0) {
result = ""+parseInt(hour)+"小时"+result;
}
return result;
}
function enclosureJHpay(params) {
var _this = this;
let userInfo = wx.getStorageSync('wx_userinfo');
return wxRequestPost({
url: api.enclosureJHpay.url,
data: {
...params,
appId: config.APPID,
openId: userInfo.openId
}
}).then(res => {
let payParams = res.data.data;
return new Promise((resolve, reject) => {
console.log(res)
wx.requestPayment({
timeStamp: payParams.timeStamp,
nonceStr: payParams.nonceStr,
package: payParams.mypackage,
signType: payParams.signType,
paySign: payParams.paySign,
success: function (res) {
console.log(res);
resolve(res);
},
fail: function (err) {
console.log(err);
reject(err)
}
})
})
})
}
function getQueryString(urlStr) {
let urlParams = {};
let str = urlStr.substr(urlStr.indexOf("?")+1); //从第一个字符开始 因为第0个是?号 获取所有除问号的所有符串
let strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
let sTemp = strs[i].split("=");
urlParams[sTemp[0]]=(sTemp[1]);
}
return urlParams
}
module.exports = {
formatTime: formatTime,
headers: headers,
wxRequest: wxRequest,
wxUpload: wxUpload,
checkMember: checkMember,
formatArea: formatArea,
fixImgUrl: fix_img_url,
countdown: count_down,
sceneParse: scene_parse,
getCurrentPageUrlWithArgs: getCurrentPageUrlWithArgs,
gotoIndex: gotoIndex,
merchantShare: merchantShare,
getQuery: getQuery,
setTabBarBadge: setTabBarBadge,
filterServiceProvidedIcon: filterServiceProvidedIcon,
wxRequestGet,
wxRequestPost,
buriedPoint,
checkLogin,
getUserInfo,
setHtmlSnip: setHtmlSnip,
getTime: getTime,
enclosureJHpay: enclosureJHpay,
getQueryString: getQueryString
}
rabbitmq rabbitmq模式 Direct模式相当于一对一模式,一个消息被发送者发送后,会被转发到一个绑定的消息队列中,然后被一个接收者接收! topic和direct的区别,没有什么大的区别,就是binding key和routing key的匹配方式可以通过通配符的方式,也就是说路由模式是topic模式的一个特例。 ..._topics rabbitmq springboot 黑马
参考链接: https://www.jb51.net/article/137220.htmimport os# os.system("python visualization_export3.py %s" % 1200)# 这样可以直接执行 visualization_export3.py __name__ 代码# 1、xlwt 模块的初级使用import xlwt..._xlwt插入公式
对于模板类A,如果模板类B把A作为成员,则模板在定义模板B之前,只需声明模板B就可以,不必给出B的定义,只要在实例化B的之前,给出A的定义就可以了。这点很像依赖于模板的函数解析。例如:#include iostream>using namespace std;template class T>class A;template class T>class B{AT> a;};templa
来源:Python中文社区OpenPyXL 使您能够以多种不同的方式设置单元格的样式。样式化单元格会让您的电子表格充满魅力!这将有助于将它们与其他电子表格区分开来。但是请不要过度使用, 如...
在Notepad++ v7.9.1版本中直接含有插件管理器。在Notepad++ 较低版本中可能就没有这个插件管理器,并且较低版本的QuickText插件功能也存在部分问题。因此,建议安装高版本的Notepad++。这里给大家提供Notepad++ v7.9.1版本下载链接,内部含有安装好的QuickText/Compare.接下来介绍几个常用插件。QuickText:一个非常出色的代码片段管理器,支持Notepad++所支持的所有语言类型,使用该插件能够很快的提高代码编写..._notepad++怎么用
有 n 个牛,每个牛有工作区间和花费。然后要你用最小的花费,使得要求覆盖的一段大区间被全部覆盖。_cleaning shifts s
一个最简单的jar包的Dockerfile制作openjdk的dockerhub地址在代码根目录创建Dockerfile文件,内容如下FROM openjdk:8-alpineMAINTAINER Teler [email protected] target/app.jar /home/app/app.jarWORKDIR /home/appENTRYPOINT ["java","-jar","app.jar"]EXPOSE 8080执行命令行docker build -t
更新2018/9/25在此代码中使用了很长时间我发现有些手机并没有真正开始在onResourceReady上运行.意味着一旦onResourceReady被调用,我得到isRunning()== false.解决方案:一开始就睡觉.@Overridepublic boolean onResourceReady(final GifDrawable resource, Object model, Ta..._android gif循环
android8.0带来的新的特性—— notification channelSDK上是这样描述channel的A representation of settings that apply to a collection of similarly themed notifications.简单的说,channel用来代表一系列相似的通知,即拥有相同特性的通知,使用channel可以避免创建通知..._"安卓应用开发中的notificationchannel channel = new notificationchannel(\"001\","
1、实现目标 输入:两个日期 输出:两个日期相差的天数2、代码实现方法1: 通过Calendar类的日期比较。注意:这里需要考虑一下: 日期是跨年份的,如一个是2012年,一个是2015年的 年份是分闰年和平年的,各自的天数不同/** * date2比date1多的天数 * @param date1 * @para..._java判断两个日期相隔天数
python基础 - 位置参数、默认参数、可变参数、关键字参数大家好,我是W在看源码的时候经常看到各式各样的参数,有的参数有默认值,有的参数没有默认值,有的参数连参数的名都没有,只能看到*args和**kwargs。这些东西到底有什么区别,怎么使用呢?接下来我们学习的顺序是位置参数、默认参数、可变参数、关键字参数。位置参数位置参数顾名思义就是与位置有关的参数,在调用函数的时候需要根据传入参..._简单描述位置参数、默认值参数、关键参数、可变长度参数的概念
1 简介vim是文本编辑器。代码补完、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。下面讲述一些必要的基本命令,而掌握好这些命令,您就能够很容易将vim当作一个通用的万能编辑器来使用了。vim自带基础教程:在任意一台装有vim的机器上,命令行中输入vimtutor 然后就可以看到文档了。另外网上也有很多例子如:http://blog.csdn.NET/niushuai666/a_vim 新建行