Uniapp VUE3 request封装

  1. request.js 
import env from '@/env.js';
import store from '@/store/index.js';
import { getTimestamp, generateAppKey } from '@/util/common.js';

let isRefreshing = false;
let subscribers = [];

function onAccessTokenFetched(newToken) {
  subscribers.forEach((callback) => callback(newToken));
  subscribers = [];
}

function addSubscriber(callback) {
  subscribers.push(callback);
}

//获取token
export const fetchToken = async () => {
  const appid = env.appId;
  const secret = env.appSecret;
  const companycode = env.companyCode;
  const timestamp = getTimestamp();
  const appkey = generateAppKey(appid, timestamp, secret);

  try {
    const { data, statusCode } = await new Promise((resolve, reject) => {
      uni.request({
        url: `${env.WebApiBase}/accessToken/getToken`,
        method: 'GET',
        timeout: 10000,
        header: {
          'Content-Type': 'application/json',
        },
        data: {
          appid,
          appkey,
          timestamp,
          companycode,
        },
        complete: (response) => {
          const { statusCode, data } = response;
          if (statusCode === 200) {
            resolve({ data, statusCode });
          } else {
            reject(new Error(`请求失败,状态码:${statusCode}`));
          }
        },
        fail: (error) => {
          reject(new Error(`网络请求失败: ${error.errMsg}`));
        },
      });
    });

    if (data.Success) {
      store.dispatch('saveToken', data.GateWayToken);
      return data.GateWayToken;
    } else {
      throw new Error(`获取 Token 失败: ${data.Message || '未知错误'}`);
    }
  } catch (error) {
    if (error.message.includes('timeout')) {
      uni.showToast({ title: '请求超时,请检查网络连接', icon: 'none' });
    } else if (error.message.includes('网络请求失败')) {
      uni.showToast({ title: '网络错误,请稍后重试', icon: 'none' });
    } else {
      uni.showToast({ title: error.message, icon: 'none' });
    }

    console.error('获取 Token 失败:', error);
    throw error;
  }
};

const request = async (options = {}, retryCount = 0) => {
  if (!store.getters.getToken && !isRefreshing) {
    await store.dispatch('fetchAndSaveToken');
  }

  // 将data对象转为查询字符串
  let queryParams = '';
    // 首先,将 param 转换为 JSON 字符串
    if (options.data.param) {
        options.data.param = JSON.stringify(options.data.param);
    }
  if (options.data) {
    queryParams = Object.keys(options.data)
      .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(options.data[key])}`)
      .join('&');
  }

  // 确保只有在 options.url 不包含 WebApiBase 时才添加它
  const finalUrl = options.url.startsWith(env.WebApiBase)
    ? options.url
    : `${env.WebApiBase}${options.url}${queryParams ? (options.url.includes('?') ? '&' : '?') + queryParams : ''}`;

  // 更新 options 对象
  options.url = finalUrl;
  options.header = {
    'Content-Type': 'application/json;charset=UTF-8',
    GateWayToken: store.getters.getToken,
    ...options.header,
  };

  options.dataType = 'json';
  options.responseType = 'text';

  return new Promise((resolve, reject) => {
    options.complete = async (response) => {

      // 确保 response 对象不为空
      if (!response) {
        reject(new Error('响应为空'));
        return;
      }

      const { statusCode, data } = response || {};

      if (statusCode === 200) {
        // 检查业务逻辑中的401错误
        if (data.StatusCode === '401' && data.Message.includes('登录已超时')) {
          if (retryCount < 1) {
            handleTokenRefresh(async (newToken) => {
              options.header['GateWayToken'] = newToken;
              resolve(await request(options, retryCount + 1));
            });
          } else {
            handleUnauthorized();
            // reject(new Error('Token刷新失败,多次尝试无效'));
          }
        } else if (data.Success) {
          resolve(data.datalist);
        } else {
                    if(data.Message == '暂无数据'){
                        resolve([]);
                    }else{
                        reject(data);
                    }
        }
      } else {
        reject(data);
      }
    };

    uni.request(options);
  });
};

const handleTokenRefresh = (retryRequest) => {
  addSubscriber(retryRequest);

  if (!isRefreshing) {
    isRefreshing = true;
    store.dispatch('fetchAndSaveToken')
      .then((newToken) => {
        onAccessTokenFetched(newToken);
      })
      .catch(() => {
        // console.error('Token刷新失败:', error);
                handleUnauthorized();
                // throw new Error('Token刷新失败,多次尝试无效');
      })
      .finally(() => {
        isRefreshing = false;
      });
  }
};

const handleUnauthorized = () => {
  store.commit('resetState');
};

export default {
  request,
  get: (url, data, options) => request({ url, data, method: 'GET', ...options }),
  post: (url, data, options) => request({ url, data, method: 'POST', ...options }),
  put: (url, data, options) => request({ url, data, method: 'PUT', ...options }),
  delete: (url, data, options) => request({ url, data, method: 'DELETE', ...options }),
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值