-你不知道的uni-app网络请求二次封装-

990 阅读3分钟

uni-app开发中,我们经常需要与后端服务器进行数据交互。为了提高开发效率、代码的可维护性以及降低重复代码的使用,我们通常会对网络请求进行封装。


二次封装的好处:

  • 简化代码,易于管理,通过.get()或者.post()等方法简单调用发送请求;
  • 请求前拦截,在header中增加token字段,设置请求头;
  • 防止请求重复发送;
  • 统一处理请求错误,根据请求回调状态码做出不同响应。
  • 在请求库中实现全局的loading功能,让用户在发送请求时能够看到加载动画,增强用户体验。

实现步骤:

1、首先在/utils/utils.js,定义toast, clearStorageSync, getStorageSync等方法。

/**
 * 提示方法
 * @param {String} title 提示文字
 * @param {String}  icon icon图片
 * @param {Number}  duration 提示时间
 */
export function toast(title, icon = 'none', duration = 1500) {
	if(title) {
		uni.showToast({
		    title,
		    icon,
		    duration
		})
	}
}
/**
 * 设置缓存
 * @param {String} key 键名
 * @param {String} data 值
 */
export function setStorageSync(key, data) {
    uni.setStorageSync(key, data)
}
/**
 * 获取缓存
 * @param {String} key 键名
 */
export function getStorageSync(key) {
    return uni.getStorageSync(key)
}
/**
 * 删除缓存
 * @param {String} key 键名
 */
export function removeStorageSync(key) {
    return uni.removeStorageSync(key)
}
/**
 * 清空缓存
 * @param {String} key 键名
 */
export function clearStorageSync() {
    return uni.clearStorageSync()
}

2、在/utils/request.js文件,定义基础请求,接收路径(url),方法(method),参数(data),请求头(header)四个参数。

import {toast, clearStorageSync, getStorageSync} from './utils'
const BASE_URL = 'https://www.baidu.com'
// 统一处理路径,参数,请求方式
uni.addInterceptor('request', {
    invoke(args) { //拦截前触发
        args.url = BASE_URL + args.url
        //设置带token请求头
        if (getStorageSync('token')) args.header["token"] = getStorageSync('token')
    },
    success(args) { //成功回调拦截
        if (!args || !args.statusCode) {
                return Promise.reject("错误的消息内容。");
        }
        //处理状态码
        if (args.statusCode !== 200) {
            if(args.statusCode === 402){
                toast("登录已过期,请重新登录")
                clearStorageSync()
                setTimeout(() => {
                        uni.navigateTo({
                                url: '/pages/User/Login'
                        })
                },1000)
            }else{
                console.log(args,'args');
                toast(args.message || "请求失败")
            }
            return Promise.resolve({ data: { code: args.statusCode,message:'请求失败' } });
        }else{
            if (!args.data || !args.data.code) {
                return Promise.resolve(args);
            }
            //处理消息码
            if (args.data && args.data.code !== 200) {
                if (args.data.code === 402) {
                    toast("请先登录")
                    setTimeout(() => {
                        //调转到登录页面
                        uni.navigateTo({
                                url: "/pages/User/Login",
                        });	
                    }, 1000);
                    return Promise.resolve(args);
            }else{
                    toast(args.data.message || "无法发起请求")
                    return Promise.resolve(args);
                }
            }
        }
        //返回消息 
        return Promise.resolve(args)
    },
    fail() { //失败回调拦截
        toast("无法发起请求")
    },
})

// 同时发送异步代码的次数,防止一次点击中有多次请求,用于处理
let ajaxTimes = 0;
const baseRequest = async (url, method, data, header) => {
    ajaxTimes++;
    uni.showLoading({
        title: "加载中",
        mask: true,
    })
    const promise = new Promise((resolve, reject) => {
        uni.request({
            url: url,
            data: data,
            method:method || 'GET',
            header: header?header:{}, 
            success: (res) => {
                    //上面已经对错误进行了处理,直接返回的就是data
                    resolve(res);
            },
            fail: (err) => {
                    reject(err)
            },
            // 完成之后关闭加载效果
            complete: () => {
                    ajaxTimes--;
                    if (ajaxTimes === 0) uni.hideLoading();
            }
        });
    });
    return Promise.resolve(promise);
}
const request = {};
['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
    request[method] = (api, data, header) => baseRequest(api, method, data, header)
})
export default request

3、使用方式

/api/user.js 文件

import request from '@/utils/request'
//个人信息
export const userInfo = data => request.get('/user/userInfo', data)

页面中使用:

import { userInfo } from '@/api/user.js'
export default {
    onLoad() {
        this.getUserinfo()
    },
    methods: {
        async getUserinfo() {
            let res = await userInfo()
        }
    }
}

结语

uni-app项目,都可以将请求二次封装,提高效率,减少冗余代码。

往期推荐