uni-app http.js 请求封装(构造函数版本)

发布时间 2023-07-17 10:00:40作者: 巫小婆
import {
    getToken,
    removeToken
} from "./auth.js"
import config from './config.js'
// 默认配置
const DEFAULT_CONFIG = {
    baseUrl: process.env.NODE_ENV === 'development'?config.url_qa_api:config.url_online_api, // 这里是自定义config 中导出的两个常量环境地址
    data: {},
    header: {
        'content-type': 'application/json;charset=UTF-8',
        'Authorization': 'Bearer ' + getToken('token'),
        'Xiot-Plat': 1
    },
    method: "POST",
    // 超时时间,单位 ms
    timeout: 60000,
    // 如果设为 json,会尝试对返回的数据做一次 JSON.parse
    dataType: 'json',
    // 设置响应的数据类型。合法值:text、arraybuffer App和支付宝小程序不支持
    responseType: 'text',
    // 验证 ssl 证书 仅App安卓端支持(HBuilderX 2.3.3+)
    sslVerify: true,
};
class Request {
    constructor(options = {}) {
        // 合并用户自定义配置
        this.config = Object.assign({}, DEFAULT_CONFIG, options);
    }
    // 请求拦截 主要是合并url,合并接口特定配置,可以根据自己情况进行扩展
    requestInterceptor(url, data, config, method) {
        const {
            baseUrl
        } = this.config

        // 拼接Url
        url = baseUrl + url;
        const configs = {
            ...this.config,
            url,
            data,
            ...config,
            method,
        };
        // 返回组装的配置
        return configs;
    }
    // 响应拦截,这里只是做了示例,可以根据自己情况进行扩展
    async responseInterceptor(res) {
        const {
            data: _data
        } = res;
        const {
            code,
            message,
            data
        } = _data;
        if (code !== "200") {
            this.handleError(message);
            if (code === 403) {
                // 清除本地token
                removeToken()
                // 关闭所有页面返回到登录页
                uni.reLaunch({
                    url: 'pages/login/index'
                })
            }

            return Promise.reject(message);
        }
        return data;
    }
    // 请求方法,做了Promise封装,返回Promise
    /**
     * @param {String} url 接口
     * @param {Object} data 参数
     * @param {Object} config 某个接口自定义配置
     * @param {String} method 请求方法
     * @returns
     */
    request(url, data, config, method) {
        // 显示loading
        uni.showLoading();
        // 请求拦截,返回处理过的结果配置
        const _config = this.requestInterceptor(url, data, config, method);
        // Promise 封装
        return new Promise((resolve, reject) => {
            uni.request({
                ..._config,
                success: (res) => {
                    // 这种简写方式一时看不懂,可以替换为注释的写法
                    this.responseInterceptor(res).then(resolve).catch(reject);
                    // this.responseInterceptor(res).then(res => {
                    //   resolve(res)
                    // }).catch(err => {
                    //   reject(err)
                    // });
                },
                fail: (err) => {
                    // 提示错误
                    this.handleError(err.message);
                    console.log("fail", err);
                },
                complete: () => {
                    // 关闭Loading
                    uni.hideLoading();
                },
            });
        });
    }

    /**
     * get请求
     * @param {String} url 接口
     * @param {Object} data 请求参数 可选
     * @param {Object} config 接口自定义配置 可选
     * @returns
     */
    get(url, data = {}, config = {}) {
        return this.request(url, data, config, "GET");
    }
    /**
     * post请求
     * @param {String} url 接口
     * @param {Object} data 请求参数 可选
     * @param {Object} config 接口自定义配置 可选
     * @returns
     */
    post(url, data = {}, config = {}) {
        return this.request(url, data, config, "POST");
    }
    // 错误提示
    handleError(title) {
        uni.showToast({
            title,
            icon: "none",
        });
    }
}

export default Request;

 http.js 代码

main.js 全局挂载如下所示(vue3 写法):

import App from './App'


// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
import Request from './common/js/http.js'
Vue.config.productionTip = false
App.mpType = 'app'

const app = new Vue({
  ...App
})
app.$mount()
// #endif

// #ifdef VUE3
import { createSSRApp } from 'vue'
import Request from './common/js/http.js'
export function createApp() {
  const app = createSSRApp(App)
  const http = new Request();
  app.config.globalProperties.$http = http
  return {
    app
  }
}
// #endif

.vue页面使用如下:
import { onMounted, ref,getCurrentInstance } from "vue"

const getData =()=>{
global.$http.post("/loginapi/login", { account: "*****",password:'****'}, {})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
}



公共api 引用写法如下

import Request from '@/common/js/http.js'
const http = new Request();
// 登录
export function login(data) {
    return http.post('/loginapi/login', data);
}
//在页面引用
login( { account: "13311111111",password:md5.hex_md5('xiezhu123').toLocaleUpperCase()})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});

auth.js 文件内容

const TokenKey = 'token';

// 认证令牌
export function getToken() {
    return uni.getStorageSync(TokenKey)
}

export function setToken(token) {
    return uni.setStorageSync(TokenKey, token)
}

export function removeToken() {
    return uni.removeStorageSync(TokenKey)
}

config.js 文件内容

export default {
    //QA2环境
    // #ifdef H5
    url_qa_api: '/dpc', //解决web跨域问题,如果需要H5,更改/dpc
    // #endif
    // #ifndef H5
    url_qa_api: "http://xxxxx.cn",
    // url_qa_api: "http://xxxxx",
    // #endif
    url_qa_api: "http://xxxxxx",
    //线上正式
    url_online_api: "https://xxxxx",
    
    
    
    //v1.0
    method_login: '/loginapi/login', //登录
}