uni-app 请求封装:打造高效、优雅的网络请求

在开发基于 uni-app 的跨平台应用时,网络请求是必不可少的功能之一。然而,直接使用 uni.request 方法会导致大量重复代码,且难以维护。因此,对请求进行封装显得尤为重要。本文将详细介绍如何封装 uni-app 的网络请求,帮助你打造高效、优雅的请求逻辑。

一、请求封装的意义

在实际开发中,网络请求通常会涉及以下问题:

  1. 重复代码:每次调用 uni.request 都需要设置 URL、请求头、超时时间等参数。

  2. 难以维护:当 Base URL 或超时时间需要修改时,需要逐个查找并替换。

  3. 错误处理分散:不同地方的请求可能需要重复处理错误逻辑,如登录状态失效、网络超时等。

通过封装请求方法,可以解决这些问题:

  1. 减少重复代码:将通用逻辑集中处理,减少重复代码。

  2. 便于维护:集中管理请求配置,修改一处即可生效。

  3. 统一错误处理:集中处理错误逻辑,提升用户体验。

二、uni-app 请求封装实现

以下是封装后的请求代码示例,我们将逐步解析其功能。

1. 基础配置

// 请求基础配置
const base_url = process.env.NODE_ENV === 'production'
  ? 'http://your scbaseurl/' // 生产环境
  : process.env.NODE_ENV === 'test'
    ? 'http://your csbaseurl/' // 测试环境
    : 'http://your hdbaseurl/'; // 开发环境(后端本地)

const timeout = 30000; // 请求超时时间:30秒

解析

  • Base URL 的动态切换:通过 process.env.NODE_ENV 判断当前环境,动态切换 Base URL。这样可以在开发、测试和生产环境中灵活切换,无需手动修改代码。

  • 超时时间:设置默认超时时间为 30 秒,可根据实际需求调整。

2. 请求头配置

export default (params) => {
  let url = params.url;
  let method = params.method || "get";
  let data = params.data || {};
  let header = {
    'Token': uni.getStorageSync('token') || '', // 从本地存储获取 Token
    'Content-Type': 'application/json;charset=UTF-8',
    'Authorization': 'Basic c2FiZXI6c2FiZXJfc2VjcmV0', // 基础认证
    ...params.header // 允许用户自定义请求头
  };

  if (method === "post") {
    header['Content-Type'] = 'application/json'; // POST 请求默认使用 JSON 格式
  }

解析

  • 通用请求头:添加了 TokenAuthorization,用于处理认证和鉴权。

  • 动态请求头:允许用户通过 params.header 自定义请求头。

  • 根据请求方法调整请求头:如果是 POST 请求,将 Content-Type 设置为 application/json

3. 请求方法封装

  return new Promise((resolve, reject) => {
    uni.request({
      url: base_url + url,
      method: method,
      header: header,
      data: data,
      timeout,
      success(response) {
        const { statusCode, data, errMsg } = response;

        if (statusCode == 200) {
          if (data.code === 0) {
            resolve(data.data); // 请求成功,返回数据
          } else if (data.code == -1) {
            console.log(data.msg);
            uni.showToast({
              title: data.msg || '未知错误', // 确保 msg 是字符串
              icon: "none",
              duration: 10000,
            });
          } else {
            // 根据返回的 code 处理不同情况
            switch (data.code) {
              case 401:
                uni.navigateTo({
                  url: "/pages/login/login",
                });
                break;
              case 404:
                uni.showToast({
                  title: '请求地址不存在...',
                  duration: 2000,
                });
                break;
              default:
                uni.showToast({
                  title: '请重试...',
                  duration: 2000,
                });
                break;
            }
          }
        } else if (statusCode == 401) {
          // 未授权,跳转到登录页面
          uni.navigateTo({
            url: "/pages/login/login",
          });
        }
      },
      fail(err) {
        console.log(err, '网络超时');
        uni.showToast({
          title: err.errMsg.indexOf('request:fail') !== -1 ? '网络连接失败' : '未知错误',
          icon: "error",
          duration: 2000
        });
        reject(err);
      },
      complete() {
        // 不管成功还是失败都会执行
        uni.hideLoading();
      }
    });
  });
};

解析

  • Promise 封装:使用 Promise 封装请求,方便在页面中使用 .then().catch() 处理请求结果。

  • 成功处理

    • 如果状态码为 200,且返回的 data.code 为 0,表示请求成功,返回数据。

    • 如果返回的 data.code 为 -1,显示错误信息。

    • 根据不同的 data.code,处理不同的错误情况(如 401 跳转到登录页面)。

  • 失败处理

    • 捕获网络请求失败的错误,并提示用户。

    • 使用 reject 将错误传递到调用处。

  • 完成处理

    • 请求完成后,隐藏加载动画。

完整的代码封装:

// 全局请求封装——也可像上述一样根据环境不同的判断
// const base_url = '/api';
 const base_url = '你的开发环境url';//开发环境
// const base_url = '你的测试环境url';//测试环境
// const base_url = '你的正式环境url';//正式环境
// 请求超时设置
const timeout = 30000;
export default (params) => {
	let url = params.url;
	let method = params.method || "get";
	let data = params.data || {};
	let header = {
		'Token': uni.getStorageSync('token') || '',
		'Content-Type': 'application/json;charset=UTF-8',
		'Authorization': 'Basic c2FiZXI6c2FiZXJfc2VjcmV0',
		...params.header
	};



	if (method === "post") {
		header['Content-Type'] = 'application/json';
	}

	return new Promise((resolve, reject) => {
		uni.request({
			url: base_url + url,
			method: method,
			header: header,
			data: data,
			timeout,
			success(response) {
				// console.log(response, '响应')
				const {
					statusCode,
					data,
					errMsg
				} = response;
				if (statusCode == 200) {
					if (data.code === 0) {
						resolve(data.data);//需要根据后端实际接口返回数据层级去resolve
						// resolve(data);
					} else if (data.code == -1) {
						console.log(data.msg)
						uni.showToast({
						      title: data.msg, // 确保 msg 是字符串,如果不是则使用 '未知错误'
							  icon: "none",
						      duration: 10000,
						    });
					} else {
						// uni.clearStorageSync();
						switch (code) {
							case 401:
								uni.navigateTo({
									url: "/pages/login/login",
								});
								break;
							case 404:
								uni.showToast({
									title: '请求地址不存在...',
									duration: 2000,
								});
								break;
							default:
								uni.showToast({
									title: '请重试...',
									duration: 2000,
								});
								break;
						}
					}
				} else if (statusCode == 401) {
					uni.navigateTo({
						url: "/pages/login/login",
					});
				}
			},
			fail(err) {
				console.log(err, '网络超时');
				uni.showToast({
					title: err.msg.indexOf('request:fail') !== -1 ? '网络连接失败' : '网络连接失败',
					icon: "error",
					duration: 2000
				});
				reject(err);
			},
			complete() {
				// 不管成功还是失败都会执行
				uni.hideLoading();
				// uni.hideToast();
			}
		});
	});
};

4. 使用示例

封装完成后,可以在页面中轻松调用封装的请求方法。以下是一个示例:

api文件夹 => login.js

// 引入 request 文件
import request from '../request/index.js'

// 登录接口
export default function loginApi(params){
	return request({
		url: 'login/loginApp',
		method: 'post',
		data: params,
	})
}

login.vue

<script>
import loginApi from "../.././api/login.js";

export default {
  data() {
    return {
      username: '',
      password: '',
      
    };
  },

  methods: {
   async handleSubmit() {
     this.showLoading(); // 显示加载提示
     let params = {
       username: this.username,
       password: this.password,
     };
     try {
       let res = await loginApi(params);
       // console.log(res, '登录');
       if (res && res.token) {
         uni.setStorageSync('token', res.token);
         uni.setStorageSync('salesman', res);
         uni.showToast({
           title: '登录成功',
           icon: 'success',
           duration: 1500
         });
         // 设置延时,确保在提示消息显示足够的时间后执行跳转
         setTimeout(() => {
             uni.switchTab({
                 url: '/pages/index/index'
             });
         }, 1500);
       } else {
         uni.showToast({
           title: '登录失败',
           icon: 'none',
           duration: 2000
         });
       }
     } catch (error) {
       uni.showToast({
         title: '登录失败,请重试',
         icon: 'none',
         duration: 2000
       });
     } finally {
       this.hideLoading(); // 隐藏加载提示
     }
   },
   
   // 显示加载提示
   showLoading() {
     uni.showLoading({
       title: '登录中...',
       mask: true // 显示透明蒙层,防止触摸穿透
     });
   },
   
   // 隐藏加载提示
   hideLoading() {
     uni.hideLoading();
   }
  }
};
</script>

三、总结

通过封装 uni-app 的网络请求,我们实现了以下目标:

  1. 减少重复代码:将通用的请求逻辑集中处理,避免重复代码。

  2. 便于维护:集中管理请求配置,修改一处即可生效。

  3. 统一错误处理:集中处理错误逻辑,提升用户体验。

封装后的请求方法不仅提高了开发效率,还增强了代码的可读性和可维护性。希望本文能帮助你在 uni-app 开发中更好地实现网络请求封装。

Uniapp 是一个跨平台的开发框架,可以同时开发小程序、H5、App 等多个平台的应用。在 Uniapp 中,可以使用原生的 API 进行网络请求,也可以使用第三方库进行封装。 以下是一个简单的 Uniapp 网络请求封装示例: 1. 创建一个请求封装的文件,例如 `api.js`: ```javascript // 导入需要的模块 import request from 'uni-request'; // 设置请求的基本配置 request.defaults.baseURL = 'http://api.example.com'; request.defaults.headers.common['Authorization'] = 'Bearer token'; // 封装 GET 请求方法 export function get(url, params) { return new Promise((resolve, reject) => { request.get(url, { params }) .then(response => { resolve(response.data); }) .catch(error => { reject(error); }); }); } // 封装 POST 请求方法 export function post(url, data) { return new Promise((resolve, reject) => { request.post(url, data) .then(response => { resolve(response.data); }) .catch(error => { reject(error); }); }); } ``` 2. 在需要使用网络请求的页面中,导入 `api.js` 文件并调用相应的方法: ```javascript import { get, post } from '@/api.js'; // 使用 GET 请求 get('/api/users', { page: 1 }) .then(data => { console.log(data); }) .catch(error => { console.error(error); }); // 使用 POST 请求 post('/api/login', { username: 'admin', password: '123456' }) .then(data => { console.log(data); }) .catch(error => { console.error(error); }); ``` 这样就可以在 Uniapp 中进行网络请求封装和调用了。封装请求的好处是可以统一处理请求的配置、错误处理等,方便管理和维护。当然,具体的封装方式可以根据项目需求进行适当的调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值