小程序开发(3)-之wx.request封装

本文介绍了微信小程序中对网络请求的封装,包括wxRequest、wxRequestPromise等函数,增强了请求的灵活性和可维护性。通过设置headers、处理loading提示、错误拦截等功能,实现了更好的接口调用管理。同时,还涉及到了本地存储、时间处理、Promise的运用以及接口数据的处理策略。
摘要由CSDN通过智能技术生成

#主要的封装是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
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值